代码改变世界

Win32 API (2013/1/17)

2013-01-17 14:41  Clingingboy  阅读(903)  评论(0编辑  收藏  举报

 

一.WM_MOUSEMOVE消息

wParam
Indicates whether various virtual keys are down. This parameter can be one or more of the following values.
MK_CONTROL
The CTRL key is down.
MK_LBUTTON
The left mouse button is down.
MK_MBUTTON
The middle mouse button is down.
MK_RBUTTON
The right mouse button is down.
MK_SHIFT
The SHIFT key is down.
MK_XBUTTON1
Windows 2000/XP: The first X button is down.
MK_XBUTTON2
Windows 2000/XP: The second X button is down.
lParam
The low-order word specifies the x-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area.

The high-order word specifies the y-coordinate of the cursor. The coordinate is relative to the upper-left corner of the client area.

二.Point的转换

1

可以用宏GET_X_LPARAM和GET_Y_LPARAM取低位和高位

#define GET_X_LPARAM(lp)                        ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp)                        ((int)(short)HIWORD(lp))

取坐标方法

            int xPos = GET_X_LPARAM(lParam);    // horizontal position 
            int yPos = GET_Y_LPARAM(lParam);    // vertical position

CPoint的封装

ATLTYPES_INLINE CPoint::CPoint(_In_ LPARAM dwPoint) throw()
{
    x = (short)GET_X_LPARAM(dwPoint);
    y = (short)GET_Y_LPARAM(dwPoint);
}

所以可以用CPoint的封装来表示坐标

case WM_MOUSEMOVE:
    {
        CPoint pt(lParam);
        OnMouseMove((UINT)wParam, pt);
    }
    break;

三.关于非客户端区域

image

Windows默认有非客户端区域,但有些客户端为了美观则去掉了默认非客户端区域的界面,绘制自己的界面.如何判断是否为非客户端区域完全由程序在WM_NCHITTEST消息中判断.

如QQ客户端,以后部分需要拖拽

image

默认非客户端区域的标题部分则提供了这样的功能,若下部分可以拖拽,为了利用这个功能,则需要在WM_NCHITTEST根据区域来进行判断,windows会对于返回的非客户区域进行处理

image

代码示例:

switch(message)
{
case WM_NCHITTEST:
    {
        bHandled=TRUE;
        return HTCAPTION;
    }
    break;
}

同理,其他的非客户区域也如此,如窗体边缘的拉缩,也可以根据区域来判断

image

代码示例:

if(WM_NCHITTEST == uMsg)
{
    CPoint point(lParam);
    DWORD nStyle = GetWindowLong(GetSafeHwnd(), GWL_STYLE);

    CRect rect;
    ::GetWindowRect(GetSafeHwnd(),&rect);
    if((nStyle & WS_MAXIMIZE))    {
            }
    else
    {
        int nMargin=2;
        if((point.x <= rect.left + 2 && point.y <= rect.top + 20) ||
            (point.x <= rect.left + 20 && point.y <= rect.top + 2) ||
            (point.x - rect.left + point.y - rect.top <= 10))
            return HTTOPLEFT;
        else if((point.x >= rect.right - 20 && point.y <= rect.top + 2) ||
            (point.x >= rect.right - 2 && point.y <= rect.top + 20) ||
            (rect.right - point.x + point.y - rect.top <= 10))
            return HTTOPRIGHT;
        else if((point.x <= rect.left + 2 && point.y >= rect.bottom - 20) ||
            (point.x <= rect.left + 20 && point.y >= rect.bottom - 2) ||
            (point.x - rect.left + rect.bottom - point.y <= 10))
            return HTBOTTOMLEFT;
        else if(point.x + point.y >=  rect.right + rect.bottom - 15)
            return HTBOTTOMRIGHT;
        else if(point.x <= rect.left + nMargin)
            return HTLEFT;
        else if(point.x >= rect.right - nMargin)
            return HTRIGHT;
        else if(point.y <= rect.top + nMargin)
            return HTTOP;
        else if(point.y >= rect.bottom - nMargin)
            return HTBOTTOM;
    }
}

四.WM_GETMINMAXINFO消息

这个消息在每次WM_SIZE之前都会触发,告诉系统窗体的最大最小区域

参考:http://blog.csdn.net/flowshell/article/details/4795581

示例:

LRESULT CMoloGUIWindow::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    MONITORINFO oMonitor = {};
    oMonitor.cbSize = sizeof(oMonitor);
    ::GetMonitorInfo(::MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTOPRIMARY), &oMonitor);

    CRect rcWork;
    if(oMonitor.dwFlags & MONITORINFOF_PRIMARY)
    {
        SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcWork, NULL);
    }
    else
    {
        rcWork = oMonitor.rcMonitor;
    }
    LPMINMAXINFO lpMMI = (LPMINMAXINFO) lParam;
    lpMMI->ptMaxPosition.x    = rcWork.left;
    lpMMI->ptMaxPosition.y    = rcWork.top;
    lpMMI->ptMaxSize.x        = rcWork.right - rcWork.left;
    lpMMI->ptMaxSize.y        = rcWork.bottom - rcWork.top;
    lpMMI->ptMinTrackSize.x = m_minSize.cx;//min width
    lpMMI->ptMinTrackSize.y = m_minSize.cy;//min width
    return 0;
}

五.WM_NCCALCSIZE消息

计算客户区域

示例:以下位置变成了(0,0)坐标

case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
    RECT rect;
    GetClientRect(hWnd, &rect) ;
    rect.left=0;
    rect.top=0;
    DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
        DT_SINGLELINE) ;

    EndPaint(hWnd, &ps);
    break;

image

 

更改默认客户区域

case WM_NCCALCSIZE:
    {
        BOOL bCalSize=(BOOL)wParam;
        NCCALCSIZE_PARAMS* pCalcParm=(NCCALCSIZE_PARAMS*)lParam;
        int myCaptionHeight = 130;  
        int myLeftBorderWeight =10;  
        int myRightBorderWeight =10;  
        int myBottomBorderWeight =10;  

        if (TRUE)  
        {  
            RECT& rc = (RECT&)pCalcParm->rgrc[0];//get the client rectangle  

            rc.top += myCaptionHeight - GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYDLGFRAME);  
            rc.left +=myLeftBorderWeight- GetSystemMetrics(SM_CYDLGFRAME);  
            rc.bottom -= myBottomBorderWeight - GetSystemMetrics(SM_CYDLGFRAME);  
            rc.right -= myRightBorderWeight - GetSystemMetrics(SM_CYDLGFRAME);  

        }  

        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    break;

这样会导致更改的原客户区域刷新机制失效,另外进行处理

参考:http://blog.csdn.net/lgstudyvc/article/details/7367806

http://blog.csdn.net/zdfcumt/article/details/5304221

http://qiusuoge.com/8687.html

 

image