cardrgnmouse.cpp

来自「一个类似windows」· C++ 代码 · 共 643 行 · 第 1/2 页

CPP
643
字号
//
//    CardLib - CardRegion mouse-related stuff
//
//    Freeware
//    Copyright J Brown 2001
//
#include <windows.h>
#include <math.h>
#include <stdio.h>

#include "cardlib.h"
#include "cardwindow.h"
#include "cardregion.h"

#if 1
#define TRACE(s)
#else
#define TRACE(s) printf("%s(%i): %s",__FILE__,__LINE__,s)
#endif

double __CARDZOOMSPEED = 32;

int ClipCard(HDC hdc, int x, int y, int width, int height);
void DrawCard(HDC hdc, int x, int y, HDC hdcSource, int width, int height);

#ifdef _DEBUG

static pDebugClickProc DebugStackClickProc = 0;

void CardLib_SetStackClickProc(pDebugClickProc proc)
{
    DebugStackClickProc = proc;
}

#endif

CardRegion *CardWindow::GetBestStack(int x, int y, int w, int h)
{
    int maxoverlap    =  0;
    int maxoverlapidx = -1;

    //find the stack which is most covered by the dropped
    //cards. Only include those which allow drops.
    //
    for(int i = 0; i < nNumCardRegions; i++)
    {
        int percent = Regions[i]->GetOverlapRatio(x, y, w, h);

        //if this stack has the biggest coverage yet
        if(percent > maxoverlap && Regions[i]->IsVisible())
        {
            maxoverlap = percent;
            maxoverlapidx = i;
        }
    }
    
    //if we found a stack to drop onto
    if(maxoverlapidx != -1)
    {
        return Regions[maxoverlapidx];
    }
    else
    {
        return 0;
    }
}

bool CardRegion::IsPointInStack(int x, int y)
{
    int axpos = xoffset < 0 ? xpos + (nNumApparentCards-1)*xoffset : xpos;
    int aypos = yoffset < 0 ? ypos + (nNumApparentCards-1)*yoffset : ypos;
    
    if(x >= axpos && x < axpos + width && y >= aypos && y < aypos + height && fVisible)
        return true;
    else
        return false;
}

int CardRegion::GetNumDragCards(int x, int y)
{
    int cardindex = 0;        //index from stack start
    int maxidx;

    //make x,y relative to the stack's upper left corner
    x -= xpos + (xoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * xoffset : 0);
    y -= ypos + (yoffset < 0 ? (nNumApparentCards/*cardstack.NumCards()*/ - 1) * yoffset : 0);
    
    //if stack is empty, cannot drag any cards from it
    if(cardstack.NumCards() <= 0)
        return 0;

    //see which card in the stack has been clicked on
    //top-bottom ordering
    if(yoffset > 0)
    {
        if(y < height - __cardheight)
            cardindex = y / yoffset;
        else
            cardindex = cardstack.NumCards() - 1;
    }
    else if(yoffset < 0)
    {
        if(y < __cardheight)
            cardindex = cardstack.NumCards() - 1;
        else
            cardindex = cardstack.NumCards() - ((y - __cardheight) / -yoffset) - 2;
    }
    else    //yoffset == 0
    {
        cardindex = cardstack.NumCards() - 1;
    }

    maxidx = cardindex;

    //if left-right
    if(xoffset > 0)
    {
        if(x < width - __cardwidth)
            cardindex = x / xoffset;
        else
            cardindex = cardstack.NumCards() - 1;
    }
    else if(xoffset < 0)
    {
        if(x < __cardwidth)
            cardindex = cardstack.NumCards() - 1;
        else
            cardindex = cardstack.NumCards() - ((x - __cardwidth) / -xoffset) - 2;
    }
    else
    {
        cardindex = cardstack.NumCards() - 1;
    }

    if(cardindex > maxidx) cardindex = maxidx;

    if(cardindex > cardstack.NumCards())
        cardindex = 1;

    //if are trying to drag too many cards at once
    return cardstack.NumCards() - cardindex;
}

bool CardRegion::CanDragCards(int iNumCards)
{
    if(iNumCards <= 0) return false;
    if(nThreedCount > 1 && iNumCards > 1) return false;

    if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
    {
//        TRACE("Failed to gain access to card stack\n");
        return false;
    }

    ReleaseMutex(mxlock);

    switch(uDragRule)
    {
    case CS_DRAG_ALL:
        return true;
        
    case CS_DRAG_TOP:

        if(iNumCards == 1)
            return true;
        else
            return false;
        
    case CS_DRAG_NONE:
        return false;
        
    case CS_DRAG_CALLBACK:
        
        if(CanDragCallback)
        {
            return CanDragCallback(*this, iNumCards);
        }
        else
        {
            return false;
        }
        
    default:
        return false;
    }
}

bool CardRegion::CanDropCards(CardStack &cards)
{
    if(WaitForSingleObject(mxlock, 0) != WAIT_OBJECT_0)
    {
        return false;
    }

    ReleaseMutex(mxlock);

    switch(uDropRule)
    {
    case CS_DROP_ALL:
        return true;

    case CS_DROP_NONE:
        return false;

    case CS_DROP_CALLBACK:
        
        if(CanDropCallback)
        {
            return CanDropCallback(*this, cards);
        }
        else
        {
            return false;
        }

    default:
        return false;
    }
}

bool CardRegion::OnLButtonDblClk(int x, int y)
{
    iNumDragCards = GetNumDragCards(x, y); 

    if(DblClickCallback)
        DblClickCallback(*this, iNumDragCards);

    return true;
}

bool CardRegion::OnLButtonDown(int x, int y)
{
    iNumDragCards = GetNumDragCards(x, y); 

#ifdef _DEBUG
    if(DebugStackClickProc)
    {
        if(!DebugStackClickProc(*this))
            return false;
    }
#endif

    if(ClickCallback)
        ClickCallback(*this, iNumDragCards);

    if(CanDragCards(iNumDragCards) != false)
    {

        //offset of the mouse cursor relative to the top-left corner
        //of the cards that are being dragged
        mousexoffset = x - xpos - xoffset * (nNumApparentCards - iNumDragCards);
        mouseyoffset = y - ypos - yoffset * (nNumApparentCards - iNumDragCards);
        
        if(xoffset < 0)
            mousexoffset += -xoffset * (iNumDragCards - 1);

        if(yoffset < 0)
            mouseyoffset += -yoffset * (iNumDragCards - 1);
        
        //remove the cards from the source stack
        dragstack = cardstack.Pop(iNumDragCards);

        //prepare the back buffer, and the drag image
        PrepareDragBitmaps(iNumDragCards);

        oldx = x - mousexoffset;
        oldy = y - mouseyoffset;
        
        Update();            //Update this stack's card count + size

        SetCapture((HWND)parentWnd);

        //set AFTER settings the dragstack...
        fMouseDragging = true;

        return true;
    }

    return false;
}

bool CardRegion::OnLButtonUp(int x, int y)
{
    CardRegion *pDestStack = 0;
    HDC hdc;
    int dropstackid = CS_DROPZONE_NODROP;
    
    RECT dragrect;
    DropZone *dropzone;

    fMouseDragging = false;

    //first of all, see if any drop zones have been registered
    SetRect(&dragrect, x-mousexoffset, y-mouseyoffset, x-mousexoffset+nDragCardWidth, y-mouseyoffset+nDragCardHeight);

    dropzone = parentWnd.GetDropZoneFromRect(&dragrect);

    if(dropzone)
    {
        dropstackid = dropzone->DropCards(dragstack);
        
        if(dropstackid != CS_DROPZONE_NODROP)
            pDestStack = parentWnd.CardRegionFromId(dropstackid);
        else
            pDestStack = 0;
    }
    else
    {
        pDestStack = parentWnd.GetBestStack(x - mousexoffset, y - mouseyoffset, nDragCardWidth, nDragCardHeight);
    }
    
    // If have found a stack to drop onto
    //
    TRACE ( "can I drop card?\n" );
    if(pDestStack && pDestStack->CanDropCards(dragstack)) 
    {
        TRACE ( "yes, dropping card\n" );
        hdc = GetDC((HWND)parentWnd);
        //            UseNicePalette(hdc);
        ZoomCard(hdc, x - mousexoffset, y  - mouseyoffset, pDestStack);
        ReleaseDC((HWND)parentWnd, hdc);
        

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?