从零开始之窗体二

窗体两大组成部分,非客户区与客户区.
大部分时候,我们编程都是针对客户区的,那么非客户区包括那几个部分呢?就我知道的列举如下:1.标题.2,标题图标,3,标题上按钮,4,边框,5,滚动条.6.菜单栏.其实工具栏以及状态栏等.所以窗口对象本身也是有很多小对象组成的.
下面看下窗体对象结构:
typedef struct _WINDOW_OBJECT
{
  /* NOTE: Do *NOT* Move this pointer anywhere in this structure! This
           is a pointer to the WINDOW structure that eventually replaces
           the WINDOW_OBJECT structure! USER32 expects this pointer to
           be here until WINDOW_OBJECT has completely been superseded! */
  PWINDOW Wnd;        窗口基本信息,昨天在"编辑框"里已经分析过

  /* Pointer to the thread information */
  PW32THREADINFO ti;                   //WIN32线程      
  /* Pointer to the desktop */
  PDESKTOPINFO Desktop;                 //桌面对象        
  /* system menu handle. */
  HMENU SystemMenu;                     //系统菜单对象 
  /* Entry in the thread's list of windows. */
  LIST_ENTRY ListEntry;                 //线程中的列表位置 
  /* Handle for the window. */
  HWND hSelf;                           //Handle
  /* Window flags. */
  ULONG Flags;                          //
  /* Handle of region of the window to be updated. */
  HANDLE UpdateRegion;                   //更新区域
  /* Handle of the window region. */
  HANDLE WindowRegion;                   //整个区域
  /* Pointer to the owning thread's message queue. */
  PUSER_MESSAGE_QUEUE MessageQueue;        //消息队列
  struct _WINDOW_OBJECT* FirstChild;       //窗口树
  struct _WINDOW_OBJECT* LastChild;
  struct _WINDOW_OBJECT* NextSibling;
  struct _WINDOW_OBJECT* PrevSibling;
  /* Entry in the list of thread windows. */
  LIST_ENTRY ThreadListEntry;              //线程列表头
  /* Handle to the parent window. */
  struct _WINDOW_OBJECT* Parent;           //父窗口 
  /* Handle to the owner window. */
  HWND hOwner;                             //拥有者窗口 
  /* DC Entries (DCE) */
  PDCE Dce;                                //设备描述符相关信息入口  
  /* Scrollbar info */
  PWINDOW_SCROLLINFO Scroll;              //滚动条信息
  PETHREAD OwnerThread;                    //当前线程
  HWND hWndLastPopup; /* handle to last active popup window (wine doesn't use pointer, for unk. reason)*/            最后一次的弹出窗口
  ULONG Status;             
  /* counter for tiled child windows */
  ULONG TiledCounter;          
  /* WNDOBJ list */
  LIST_ENTRY WndObjListHead;                //线程窗口列表头
} WINDOW_OBJECT; /* PWINDOW_OBJECT already declared at top of file */

其实创建一个窗口过程是蛮复杂的,不管是CreateWindow亦或是CreateWindowEx最终都是调用系统服务:NtUserCreateWindowEx,很显然也是win32k里一导出函数.然后它再调用co_IntCreateWindowEx ---> UserCreateObject创建窗体对象.其实这其中还做了非常多的事情,比如创建SystemMenu,设置窗口菜单,设置HOOK等东西,还有对于非客户区的初始化只是co_IntSendMessage(Window->hSelf, M_NCCREATE, 0, (LPARAM) &Cs)而已.

系统默认的窗口回调函数(这里请注意,除了公共的默认处理函数以外,WINDOWS通用控件也有自己的默认函数):
LRESULT WINAPI
User32DefWindowProc(HWND hWnd,
            UINT Msg,
            WPARAM wParam,
            LPARAM lParam,
            BOOL bUnicode)
{
    switch (Msg)
    {
    case WM_NCPAINT:
    {
            return DefWndNCPaint(hWnd, (HRGN)wParam, -1);          //非客户区画图消息,看下面分解
        }

        case WM_NCCALCSIZE:                     //返回需要画的一些状态
        {
            return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
        }

        case WM_POPUPSYSTEMMENU:          //系统弹出菜单
        {
            /* This is an undocumented message used by the windows taskbar to       //注意,这是一个winodows未公开的消息,主要是工具栏使用
               display the system menu of windows that belong to other processes. */
            HMENU menu = GetSystemMenu(hWnd, FALSE);

            if (menu)
                TrackPopupMenu(menu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON,             //这个函数在菜单那里已经说得很明白了
                               LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
            return 0;
        }

        case WM_NCACTIVATE:
        
            return DefWndNCActivate(hWnd, wParam);               //只简单的调用下 DefWndNCPaint(hWnd, (HRGN)1, wParam)后return True;

        }

        case WM_NCHITTEST:
        {
            POINT Point;
            Point.x = GET_X_LPARAM(lParam);
            Point.y = GET_Y_LPARAM(lParam);
            return (DefWndNCHitTest(hWnd, Point));        //只是简单的判断参数点位置,并返回
        }

        case WM_LBUTTONDOWN:
        case WM_RBUTTONDOWN:
        case WM_MBUTTONDOWN:
            iF10Key = iMenuSysKey = 0;              //只是简单判断是否是菜单键
            break;

        case WM_NCLBUTTONDOWN:
        {  
            return (DefWndNCLButtonDown(hWnd, wParam, lParam));     //看下面分解
        }

        case WM_LBUTTONDBLCLK:
            return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));   //看下面分解

        case WM_NCLBUTTONDBLCLK:
        {
            return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));  //
        }

        case WM_WINDOWPOSCHANGING:
        {
            return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));       //看下面分解
        }

        case WM_WINDOWPOSCHANGED:
        {
            return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));      //看下面分解
        }

        case WM_NCRBUTTONDOWN:                //非客户区按下
        {
            /* in Windows, capture is taken when right-clicking on the caption bar */
            if (wParam == HTCAPTION)
            {
                SetCapture(hWnd);       //此时直接设置鼠标
            }
            break;
        }

        case WM_RBUTTONUP:    
        {
            POINT Pt;
            if (hWnd == GetCapture())
            {
                ReleaseCapture();
            }
            Pt.x = GET_X_LPARAM(lParam);
            Pt.y = GET_Y_LPARAM(lParam);
            ClientToScreen(hWnd, &Pt);
            lParam = MAKELPARAM(Pt.x, Pt.y);
            if (bUnicode)
            {
                SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);       //右键处理,负责WM_CONTEXTMENU支持
            }
            else
            {
                SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
            }
            break;
        }

        case WM_NCRBUTTONUP:
          /*
           * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
           * in Windows), but what _should_ we do? According to MSDN :
           * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
           * message to the window". When is it appropriate?
           */
            break;          

        case WM_CONTEXTMENU:
        {
            if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
            {
                if (bUnicode)
                {
                    SendMessageW(GetParent(hWnd), Msg, wParam, lParam);   //由此可见,WM_CONTEXTMENU消息是要往上传递的,本身不是处理,注意windows许多消息是要上传的.
                }
                else
                {
                    SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
                }
            }
            else
            {
                POINT Pt;
                DWORD Style;
                LONG HitCode;

                Style = GetWindowLongPtrW(hWnd, GWL_STYLE);

                Pt.x = GET_X_LPARAM(lParam);
                Pt.y = GET_Y_LPARAM(lParam);
                if (Style & WS_CHILD)
                {
                    ScreenToClient(GetParent(hWnd), &Pt);
                }

                HitCode = DefWndNCHitTest(hWnd, Pt);

                if (HitCode == HTCAPTION || HitCode == HTSYSMENU)  //系统菜单处理
                {
                    HMENU SystemMenu;
                    UINT Flags;

                    if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
                    {
                      MenuInitSysMenuPopup(SystemMenu, GetWindowLongPtrW(hWnd, GWL_STYLE),
                                           GetClassLongPtrW(hWnd, GCL_STYLE), HitCode);

                      if(HitCode == HTCAPTION)
                        Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
                      else
                        Flags = TPM_LEFTBUTTON;

                      TrackPopupMenu(SystemMenu, Flags,
                                     Pt.x, Pt.y, 0, hWnd, NULL);
                    }
                }
        }
            break;
        }

        case WM_PRINT:
        {
            DefWndPrint(hWnd, (HDC)wParam, lParam);  //系统默认打印消息
            return (0);
        }

        case WM_SYSCOLORCHANGE:     //系统颜色改变消息
        {
            /* force to redraw non-client area */
            DefWndNCPaint(hWnd, (HRGN)1, -1);
            /* Use InvalidateRect to redraw client area, enable
             * erase to redraw all subcontrols otherwise send the
             * WM_SYSCOLORCHANGE to child windows/controls is required
             */
            InvalidateRect(hWnd,NULL,TRUE);
            return (0);
        }

        case WM_PAINTICON:
        case WM_PAINT:                   //处理画系统图标消息
        {
            PAINTSTRUCT Ps;
            HDC hDC = BeginPaint(hWnd, &Ps);
            if (hDC)
            {
                HICON hIcon;

                if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
                    (hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON)) != NULL)
                {
                    RECT ClientRect;
                    INT x, y;
                    GetClientRect(hWnd, &ClientRect);
                    x = (ClientRect.right - ClientRect.left -
                         GetSystemMetrics(SM_CXICON)) / 2;
                    y = (ClientRect.bottom - ClientRect.top -
                         GetSystemMetrics(SM_CYICON)) / 2;
                    DrawIcon(hDC, x, y, hIcon);            //画系统图标对象
                }
                EndPaint(hWnd, &Ps);
            }
            return (0);
        }

        case WM_SYNCPAINT:               //??
        {
            HRGN hRgn;
            hRgn = CreateRectRgn(0, 0, 0, 0);
            if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
            {
                RedrawWindow(hWnd, NULL, hRgn,
                    RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
                    RDW_ALLCHILDREN);
            }
            DeleteObject(hRgn);
            return (0);
        }

        case WM_SETREDRAW:               //重画消息
        {
            DefWndSetRedraw(hWnd, wParam);      
            return (0);
        }

        case WM_CLOSE:        //关闭窗口,注意这里直接执行的是DestroyWindow
        {
            DestroyWindow(hWnd);
            return (0);
        }

        case WM_MOUSEACTIVATE:        //鼠标活动窗口
        {
            if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)       //又是一个要上传的消息               
            {
                LONG Ret;
                if (bUnicode)
                {
                    Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
                                       wParam, lParam);
                }
                else
                {
                    Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
                                       wParam, lParam);
                }
                if (Ret)
                {
                    return (Ret);
                }
            }
            return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
        }

        case WM_ACTIVATE:     //激活窗口
        {
            /* Check if the window is minimized. */
            if (LOWORD(wParam) != WA_INACTIVE &&
                !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE))
            {
                SetFocus(hWnd);
            }
            break;
        }

        case WM_MOUSEWHEEL:  //又是一个要上传的消息 
        {
            if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
            {
                if (bUnicode)
                {
                    return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
                                         wParam, lParam));
                }
                else
                {
                    return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
                                         wParam, lParam));
                }
            }
            break;
        }

        case WM_ERASEBKGND:
        case WM_ICONERASEBKGND:          
        {
            RECT Rect;
            HBRUSH hBrush = (HBRUSH)GetClassLongPtrW(hWnd, GCL_HBRBACKGROUND);

            if (NULL == hBrush)
            {
                return 0;
            }
            if (GetClassLongPtrW(hWnd, GCL_STYLE) & CS_PARENTDC)        //CS_PARENTDC决定是否使用父窗口设备描述符
            {
                /* can't use GetClipBox with a parent DC or we fill the whole parent */
                GetClientRect(hWnd, &Rect);
                DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
            }
            else
            {
                GetClipBox((HDC)wParam, &Rect);
            }
            FillRect((HDC)wParam, &Rect, hBrush);
            return (1);
        }

        case WM_CTLCOLORMSGBOX:
        case WM_CTLCOLOREDIT:
        case WM_CTLCOLORLISTBOX:
        case WM_CTLCOLORBTN:
        case WM_CTLCOLORDLG:
        case WM_CTLCOLORSTATIC:
        case WM_CTLCOLORSCROLLBAR:               //控件获取颜色消息
        return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);

        case WM_CTLCOLOR:          //取得控件颜色
            return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));

        case WM_SETCURSOR:               //设置鼠标
        {
            ULONG Style = GetWindowLongPtrW(hWnd, GWL_STYLE);

            if (Style & WS_CHILD)  //又是一个要上传的消息 
            {
                if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
                {
                    BOOL bResult;
                    if (bUnicode)
                    {
                        bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
                                               wParam, lParam);
                    }
                    else
                    {
                        bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
                                               wParam, lParam);
                    }
                    if (bResult)
                    {
                        return(TRUE);
                    }
                }
            }
            return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
        }

        case WM_SYSCOMMAND:
            return (DefWndHandleSysCommand(hWnd, wParam, lParam));  //Ok

        case WM_KEYDOWN:
            if(wParam == VK_F10) iF10Key = VK_F10;  
            break;

        /* FIXME: This is also incomplete. */
        case WM_SYSKEYDOWN:
        {
            if (HIWORD(lParam) & KEYDATA_ALT)
            {
                HWND top = GetAncestor(hWnd, GA_ROOT);
             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
                if ( (wParam == VK_MENU || wParam == VK_LMENU
                                    || wParam == VK_RMENU) && !iMenuSysKey )
                {
                   iMenuSysKey = 1;
                   /* mimic behaviour of XP, sending a WM_SYSCOMMAND when pressing <alt> */
                   SendMessageW( top, WM_SYSCOMMAND, SC_KEYMENU, 0L );
                }
                else
                   iMenuSysKey = 0;

                iF10Key = 0;

                if (wParam == VK_F4) /* Try to close the window */  //ALT+F4处理函数
                {
                    if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
                    {
                        if (bUnicode)
                            PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
                        else
                            PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
                    }
                }
                else if (wParam == VK_SNAPSHOT)        //当前窗口截屏消息处理
                {
                    HWND hwnd = hWnd;
                    while (GetParent(hwnd) != NULL)
                    {
                        hwnd = GetParent(hwnd);
                    }
                    DefWndScreenshot(hwnd);              
                }
            }
            else if( wParam == VK_F10 )
                iF10Key = 1;
            else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
                SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
            break;
        }

        case WM_KEYUP:
        case WM_SYSKEYUP:
        {
           /* Press and release F10 or ALT */
            if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
                 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
                SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );  //向祖先窗口传送消息
            iMenuSysKey = iF10Key = 0;
            break;
        }

        case WM_SYSCHAR:
        {
            iMenuSysKey = 0;
            if (wParam == '\r' && IsIconic(hWnd))
            {
                PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
                break;
            }
            if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
            {
                if (wParam == '\t' || wParam == '\x1b') break;
                if (wParam == ' ' && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
                    SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
                else
                    SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
            }
            else /* check for Ctrl-Esc */
                if (wParam != '\x1b') MessageBeep(0);
            break;
        }

        case WM_SHOWWINDOW:
        {
            if (lParam) // Call when it is necessary.
               NtUserMessageCall( hWnd, Msg, wParam, lParam, 0, FNID_DEFWINDOWPROC, FALSE); 
            break;
        }

        case WM_CANCELMODE:         //前几天在弹出菜单见到过此消息
        {
            iMenuSysKey = 0;
            /* FIXME: Check for a desktop. */
            if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
            if (GetCapture() == hWnd)
            {
                ReleaseCapture();  //释放鼠标
            }
            break;
        }

        case WM_VKEYTOITEM:
        case WM_CHARTOITEM:
            return (-1);
/*
        case WM_DROPOBJECT:
            return DRAG_FILE;
*/
        case WM_QUERYDROPOBJECT:
        {
            if (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
            {
                return(1);
            }
            break;
        }

        case WM_QUERYDRAGICON:
        {
            UINT Len;
            HICON hIcon;

            hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON);
            if (hIcon)
            {
                return ((LRESULT)hIcon);
            }
            for (Len = 1; Len < 64; Len++)
            {
                if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
                {
                    return((LRESULT)hIcon);
                }
            }
            return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
        }

        /* FIXME: WM_ISACTIVEICON */

        case WM_NOTIFYFORMAT:
        {
            if (lParam == NF_QUERY)
                return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
            break;
        }

        case WM_SETICON:  //设置图标
        {
           INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
           HICON hOldIcon = (HICON)GetClassLongPtrW(hWnd, Index);
           SetClassLongPtrW(hWnd, Index, lParam);
           SetWindowPos(hWnd, 0, 0, 0, 0, 0,
               SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
               SWP_NOACTIVATE | SWP_NOZORDER);
           return ((LRESULT)hOldIcon);
        }

        case WM_GETICON:       //获取图标
        {
            INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
            return (GetClassLongPtrW(hWnd, Index));
        }

        case WM_HELP:            //帮助,上传消息
        {
            if (bUnicode)
            {
                SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
            }
            else
            {
                SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
            }
            break;
        }

        case WM_SYSTIMER:               //系统时钟,处理插入符的,昨天在编辑框时候就提到过
        {
          THRDCARETINFO CaretInfo;
          switch(wParam)
          {
            case 0xffff: /* Caret timer */                    //插入符TIMER的ID
              /* switch showing byte in win32k and get information about the caret */
              if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
              {
                DrawCaret(hWnd, &CaretInfo);
              }
              break;
          }
          break;
        }

        case WM_QUERYOPEN:
        case WM_QUERYENDSESSION:
        {
            return (1);
        }

        case WM_INPUTLANGCHANGEREQUEST://????
        {
            HKL NewHkl;

            if(wParam & INPUTLANGCHANGE_BACKWARD
               && wParam & INPUTLANGCHANGE_FORWARD)
            {
                return FALSE;
            }

            //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?

            if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
            else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
            else NewHkl = (HKL) lParam;

            NtUserActivateKeyboardLayout(NewHkl, 0);

            return TRUE;
        }

        case WM_INPUTLANGCHANGE:   //???
        {
            int count = 0;
            HWND *win_array = WIN_ListChildren( hWnd );

            if (!win_array)
                break;
            while (win_array[count])
                SendMessageW( win_array[count++], WM_INPUTLANGCHANGE, wParam, lParam);
            HeapFree(GetProcessHeap(),0,win_array);
            break;
        }

        case WM_QUERYUISTATE:        //查询UI状态
        {
            LRESULT Ret = 0;
            PWINDOW Wnd = ValidateHwnd(hWnd);
            if (Wnd != NULL)
            {
                if (Wnd->HideFocus)
                    Ret |= UISF_HIDEFOCUS;
                if (Wnd->HideAccel)
                    Ret |= UISF_HIDEACCEL;
            }
            return Ret;
        }

        case WM_CHANGEUISTATE:       //UI状态改变消息处理
        {
            BOOL AlwaysShowCues = FALSE;
            WORD Action = LOWORD(wParam);
            WORD Flags = HIWORD(wParam);
            PWINDOW Wnd;

            SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
            if (AlwaysShowCues)
                break;

            Wnd= ValidateHwnd(hWnd);
            if (!Wnd || lParam != 0)
                break;

            if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
                break;

            if (Flags & UISF_ACTIVE)
            {
                WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
            }

            if (Action == UIS_INITIALIZE)
            {
                PDESKTOPINFO Desk = GetThreadDesktopInfo();
                if (Desk == NULL)
                    break;

                Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
                Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;

                /* We need to update wParam in case we need to send out messages */
                wParam = MAKEWPARAM(Action, Flags);
            }

            switch (Action)
            {
                case UIS_SET:
                    /* See if we actually need to change something */
                    if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
                        break;
                    if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
                        break;

                    /* Don't need to do anything... */
                    return 0;

                case UIS_CLEAR:
                    /* See if we actually need to change something */
                    if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
                        break;
                    if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
                        break;

                    /* Don't need to do anything... */
                    return 0;

                default:
                    WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
                    break;
            }

            if ((Wnd->Style & WS_CHILD) && Wnd->Parent != NULL)
            {
                /* We're a child window and we need to pass this message down until
                   we reach the root */
                hWnd = UserHMGetHandle((PWINDOW)DesktopPtrToUser(Wnd->Parent));
            }
            else
            {
                /* We're a top level window, we need to change the UI state */
                Msg = WM_UPDATEUISTATE;
            }

            if (bUnicode)
                return SendMessageW(hWnd, Msg, wParam, lParam);
            else
                return SendMessageA(hWnd, Msg, wParam, lParam);
        }

        case WM_UPDATEUISTATE:            //更新UI状态
        {
            BOOL Change = TRUE;
            BOOL AlwaysShowCues = FALSE;
            WORD Action = LOWORD(wParam);
            WORD Flags = HIWORD(wParam);
            PWINDOW Wnd;

            SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
            if (AlwaysShowCues)
                break;

            Wnd = ValidateHwnd(hWnd);
            if (!Wnd || lParam != 0)
                break;

            if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
                break;

            if (Flags & UISF_ACTIVE)
            {
                WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
            }

            if (Action == UIS_INITIALIZE)
            {
                PDESKTOPINFO Desk = GetThreadDesktopInfo();
                if (Desk == NULL)
                    break;

                Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
                Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;

                /* We need to update wParam for broadcasting the update */
                wParam = MAKEWPARAM(Action, Flags);
            }

            switch (Action)
            {
                case UIS_SET:
                    /* See if we actually need to change something */
                    if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
                        break;
                    if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
                        break;

                    /* Don't need to do anything... */
                    Change = FALSE;
                    break;

                case UIS_CLEAR:
                    /* See if we actually need to change something */
                    if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
                        break;
                    if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
                        break;

                    /* Don't need to do anything... */
                    Change = FALSE;
                    break;

                default:
                    WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
                    return 0;
            }

            /* Pack the information and call win32k */
            if (Change)
            {
                if (!NtUserCallTwoParam((DWORD)hWnd, (DWORD)Flags | ((DWORD)Action << 3), TWOPARAM_ROUTINE_ROS_UPDATEUISTATE))
                    break;
            }

            /* Always broadcast the update to all children */
            EnumChildWindows(hWnd,                                 //向所有窗口发送UI更新消息
                             UserSendUiUpdateMsg,
                             (LPARAM)wParam);

            break;
        }

    }
    return 0;
}

windows是消息驱动的,上面的默认函数可以说是消息机制最重要的部分之一,消息来源:1.大部分消息来源于键盘和鼠标,或其引起的.  2.来源于本身的消息处理函数.  3.来源于系统.  4.来源于其他的应用程序,当然也可以把这归结于来源于系统.废话不多说.具体看默认窗口过程调用的函数吧.

LRESULT
DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active)       //系统默认的非客户区画图函数
{
   HDC hDC;
   DWORD Style, ExStyle;
   HWND Parent;
   RECT ClientRect, WindowRect, CurrentRect, TempRect;

   if (!IsWindowVisible(hWnd))  //通过判断当前窗口以父窗口的句柄(!(Wnd->Style & WS_VISIBLE))
      return 0;

   Style = GetWindowLongPtrW(hWnd, GWL_STYLE);

   hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN);  //获得需要更新的DC,如果没有需要更新则直接退出
   if (hDC == 0)
   {
      return 0;
   }

   Parent = GetParent(hWnd);
   ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
   if (Active == -1)
   {
      if (ExStyle & WS_EX_MDICHILD)
      {
         Active = IsChild(GetForegroundWindow(), hWnd);
         if (Active)
            Active = (hWnd == (HWND)SendMessageW(Parent, WM_MDIGETACTIVE, 0, 0));
      }
      else
      {
         Active = (GetForegroundWindow() == hWnd);
      }
   }
   GetWindowRect(hWnd, &WindowRect);  //取得整个窗口RECT
   GetClientRect(hWnd, &ClientRect);  //取得客户区RECT

   CurrentRect.top = CurrentRect.left = 0;                          //计算非客户区RECT
   CurrentRect.right = WindowRect.right - WindowRect.left;
   CurrentRect.bottom = WindowRect.bottom - WindowRect.top;       //以0为边界,取得整个RECT

   /* Draw outer edge */
   if (UserHasWindowEdge(Style, ExStyle))  //通过EXSTYLE类型,比如WS_THICKFRAME来判断
   {
      DrawEdge(hDC, &CurrentRect, EDGE_RAISED, BF_RECT | BF_ADJUST);   //画连线,这里是直接调用API画线,代码很简单,这里不列
   } else
   if (ExStyle & WS_EX_STATICEDGE)
   {
#if 0
      DrawEdge(hDC, &CurrentRect, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);
#else
      SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW));   //画阴影
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, 1, PATCOPY);  //上下阴影
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);

      SelectObject(hDC, GetSysColorBrush(COLOR_BTNHIGHLIGHT));      //左右阴影颜色        
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, 1, PATCOPY);       
      PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);

      InflateRect(&CurrentRect, -1, -1);
#endif
   }

   /* Firstly the "thick" frame */
   if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
   {
      DWORD Width =
         (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
         GetSystemMetrics(SM_CXBORDER);
      DWORD Height =
         (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *
         GetSystemMetrics(SM_CYBORDER);

      SelectObject(hDC, GetSysColorBrush(Active ? COLOR_ACTIVEBORDER :
         COLOR_INACTIVEBORDER));

      /* Draw frame */  画边框
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#ifdef __REACTOS__
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
      PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#else
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
      PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#endif

      InflateRect(&CurrentRect, -Width, -Height);     //计算大小
   }

   /* Now the other bit of the frame */
   if (Style & (WS_DLGFRAME | WS_BORDER) || ExStyle & WS_EX_DLGMODALFRAME)
   {
      DWORD Width = GetSystemMetrics(SM_CXBORDER);
      DWORD Height = GetSystemMetrics(SM_CYBORDER);

      SelectObject(hDC, GetSysColorBrush(
         (ExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :
         (ExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :
         (Style & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :
         COLOR_WINDOWFRAME));

      /* Draw frame */
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#ifdef __REACTOS__
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
      PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#else
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
      PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#endif

      InflateRect(&CurrentRect, -Width, -Height);
   }

   /* Draw caption */    //画标题
   if ((Style & WS_CAPTION) == WS_CAPTION) 判断是否存在标题
   {
      DWORD CaptionFlags = DC_ICON | DC_TEXT | DC_BUTTONS;  //默认的存在图标,Caption以及按钮
      HPEN PreviousPen;
      BOOL Gradient = FALSE;

      if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS, 0, &Gradient, 0) && Gradient)
      {
        CaptionFlags |= DC_GRADIENT;              //判断标题是否运行渐近色
      }

      TempRect = CurrentRect;

      if (Active)
      {
         CaptionFlags |= DC_ACTIVE;               //活动窗口
      }

      if (ExStyle & WS_EX_TOOLWINDOW)               
      {
         CaptionFlags |= DC_SMALLCAP;              //小图标     
         TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMCAPTION) - 1; 这里注意,如果是WS_EX_TOOLWINDOW高度大小不一样
         CurrentRect.top += GetSystemMetrics(SM_CYSMCAPTION);
      }
      else
      {
         TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYCAPTION) - 1;
         CurrentRect.top += GetSystemMetrics(SM_CYCAPTION);
      }

      NtUserDrawCaption(hWnd, hDC, &TempRect, CaptionFlags);   //调用系统服务,来画标题,但是这里只画窗口图标以及TEXT

      /* Draw buttons */
      if (Style & WS_SYSMENU)       //画系统按钮
      {
         UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONCLOSE);
         if ((Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) && !(ExStyle & WS_EX_TOOLWINDOW))  //工具栏窗口是没有最小化按钮和最大化按钮
         {
            UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMIN);
            UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMAX);
         }
      }
      if(!(Style & WS_MINIMIZE))
      {
        /* Line under caption */        //画TEXT下方线条
        PreviousPen = SelectObject(hDC, GetSysColorPen(
           ((ExStyle & (WS_EX_STATICEDGE | WS_EX_CLIENTEDGE |
                        WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
           COLOR_WINDOWFRAME : COLOR_3DFACE));
        MoveToEx(hDC, TempRect.left, TempRect.bottom, NULL);
        LineTo(hDC, TempRect.right, TempRect.bottom);
        SelectObject(hDC, PreviousPen);
      }
   }

   if(!(Style & WS_MINIMIZE))
   {
     HMENU menu = GetMenu(hWnd);
     /* Draw menu bar */   //画菜单栏
     if (menu && !(Style & WS_CHILD))
     {
        TempRect = CurrentRect;
        TempRect.bottom = TempRect.top + (UINT)NtUserSetMenuBarHeight(menu, 0);
        CurrentRect.top += MenuDrawMenuBar(hDC, &TempRect, hWnd, FALSE);
     }

     if (ExStyle & WS_EX_CLIENTEDGE)     //画客户区四周的边线
     {
        DrawEdge(hDC, &CurrentRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
     }

     /* Draw the scrollbars */   //画滚动条
     if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
         IntIsScrollBarVisible(hWnd, OBJID_VSCROLL) && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))
     {
        RECT ParentClientRect;

        TempRect = CurrentRect;
        if (ExStyle & WS_EX_LEFTSCROLLBAR)
           TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
        else
           TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
        TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
        FillRect(hDC, &TempRect, GetSysColorBrush(COLOR_BTNFACE));
        /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
        if(Parent)
          GetClientRect(Parent, &ParentClientRect);
        if (HASSIZEGRIP(Style, ExStyle, GetWindowLongPtrW(Parent, GWL_STYLE), WindowRect, ParentClientRect))
        {
           DrawFrameControl(hDC, &TempRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);  //这里和画标题按钮调用的是一个函数,只是参数不同,滚动条的LINEBUTTON
        }
        IntDrawScrollBar(hWnd, hDC, SB_VERT);  //画滚动条具体调用
        IntDrawScrollBar(hWnd, hDC, SB_HORZ);
     }
     else
     {           //这里可能有点问题,因为没有计算CurrentRect
        if (Style & WS_VSCROLL && IntIsScrollBarVisible(hWnd, OBJID_VSCROLL))
           IntDrawScrollBar(hWnd, hDC, SB_VERT);
        else if (Style & WS_HSCROLL && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))
           IntDrawScrollBar(hWnd, hDC, SB_HORZ);
     }
   }

   ReleaseDC(hWnd, hDC);

   return 0;
}

处理系统按钮函数
LRESULT
DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
    switch (wParam)
    {
        case HTCAPTION:
        {
            HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
            if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
            {
                SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
            }
            break;
        }
        case HTSYSMENU:
        {
      if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_SYSMENU)
            {
          SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
               lParam);
        }
      break;
        }
        case HTMENU:
        {
            SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
            break;
        }
        case HTHSCROLL:
        {
            SendMessageW(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
            break;
        }
        case HTVSCROLL:
        {
            SendMessageW(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
            break;
        }
        case HTMINBUTTON:
        case HTMAXBUTTON:
        case HTCLOSE:
        {
          DefWndDoButton(hWnd, wParam);  //也是通过发送WM_SYSCOMMAND消息处理
          break;
        }
        case HTLEFT:
        case HTRIGHT:
        case HTTOP:
        case HTBOTTOM:
        case HTTOPLEFT:
        case HTTOPRIGHT:
        case HTBOTTOMLEFT:
        case HTBOTTOMRIGHT:
        {
            SendMessageW(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT - WMSZ_LEFT), lParam);
            break;
        }
    }
    return(0);
}
以上函数可以看到,几乎所有处理都是通过WM_SYSCOMMAND,可见WM_SYSCOMMAND之重要程度

鼠标双击函数
LRESULT
DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  ULONG Style;

  Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
  switch(wParam)
  {
    case HTCAPTION:
    {
      /* Maximize/Restore the window */
      if((Style & WS_CAPTION) == WS_CAPTION && (Style & WS_MAXIMIZEBOX))
      {
        SendMessageW(hWnd, WM_SYSCOMMAND, ((Style & (WS_MINIMIZE | WS_MAXIMIZE)) ? SC_RESTORE : SC_MAXIMIZE), 0);
      }
      break;
    }
    case HTSYSMENU:
    {
      SendMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
      break;
    }
    default:
      return DefWndNCLButtonDown(hWnd, wParam, lParam);
  }
  return(0);
}
可见,双击函数也是通过WM_SYSCOMMAND处理的,其实这也说明了一个问题,那就是系统默认的本身只处理系统相关的命令,比如WM_SYSCOMMAND,至于应用程序可以自己处理.

正在移动处理消息
LRESULT
DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
{
    POINT maxTrack, minTrack;
    LONG style = GetWindowLongPtrA(hWnd, GWL_STYLE);

    if (Pos->flags & SWP_NOSIZE) return 0;
    if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
    {
        WinPosGetMinMaxInfo(hWnd, NULL, NULL, &minTrack, &maxTrack);  //取得可以移动的最大位置,以下根据其处理
        Pos->cx = min(Pos->cx, maxTrack.x);
        Pos->cy = min(Pos->cy, maxTrack.y);
        if (!(style & WS_MINIMIZE))
        {
            if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
            if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
        }
    }
    else
    {
        Pos->cx = max(Pos->cx, 0);
        Pos->cy = max(Pos->cy, 0);
    }
    return 0;
}

移动改变完成处理消息
LRESULT
DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
{
  RECT Rect;

  GetClientRect(hWnd, &Rect);
  MapWindowPoints(hWnd, (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD ?
                         GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);

  if (! (Pos->flags & SWP_NOCLIENTMOVE))  //判断是否SWP_NOCLIENTMOVE,是就发送WM_MOVE消息
    {
      SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));   //
    }

  if (! (Pos->flags & SWP_NOCLIENTSIZE))
    {
      WPARAM wp = SIZE_RESTORED;
      if (IsZoomed(hWnd))
        {
          wp = SIZE_MAXIMIZED;
        }
      else if (IsIconic(hWnd))
        {
          wp = SIZE_MINIMIZED;
        }
      SendMessageW(hWnd, WM_SIZE, wp,              //可以看到WM_SIZE也是此时发送的
                   MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
    }

  return 0;
}

系统命令处理消息函数
LRESULT
DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
  WINDOWPLACEMENT wp;
  POINT Pt;

#if 0
  if (ISITHOOKED(WH_CBT))
  {
     if (NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, 0, FNID_DEFWINDOWPROC, FALSE))
        return 0;
  }
#endif
  switch (wParam & 0xfff0)
    {
      case SC_MOVE:
      case SC_SIZE:  //移动窗口
    DefWndDoSizeMove(hWnd, wParam);
    break;
      case SC_MINIMIZE:     //最小化窗口
        wp.length = sizeof(WINDOWPLACEMENT);
        if(GetWindowPlacement(hWnd, &wp))
        {
          wp.showCmd = SW_MINIMIZE;
          SetWindowPlacement(hWnd, &wp);
        }
        break;         
      case SC_MAXIMIZE:    //最大化窗口
        wp.length = sizeof(WINDOWPLACEMENT);
        if(GetWindowPlacement(hWnd, &wp))
        {
          wp.showCmd = SW_MAXIMIZE;
          SetWindowPlacement(hWnd, &wp);
        }
        break;
      case SC_RESTORE:     //还原窗口
        wp.length = sizeof(WINDOWPLACEMENT);
        if(GetWindowPlacement(hWnd, &wp))
        {
          wp.showCmd = SW_RESTORE;
          SetWindowPlacement(hWnd, &wp);
        }
        break;
      case SC_CLOSE:       //关闭窗口
        SendMessageA(hWnd, WM_CLOSE, 0, 0);
        break;
      case SC_MOUSEMENU:     //弹出系统菜单
        {
          Pt.x = (short)LOWORD(lParam);
          Pt.y = (short)HIWORD(lParam);
          MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
        }
    break;
      case SC_KEYMENU:        //键盘弹出系统菜单  
        MenuTrackKbdMenuBar(hWnd, wParam, (WCHAR)lParam);
    break;
      case SC_VSCROLL:
      case SC_HSCROLL:           //滚动条处理
        {
          Pt.x = (short)LOWORD(lParam);            
          Pt.y = (short)HIWORD(lParam);
          DefWndTrackScrollBar(hWnd, wParam, Pt);
        }
    break;

      default:
    /* FIXME: Implement */
        UNIMPLEMENTED;
        break;
    }

  return(0);
}

通过以上学习,可以实现:
1.如何通过WM_SYSCOMMAND弹出系统菜单:PostMessage(Handle,WM_SYSCOMMAND,SC_KEYMENU + HTSYSMENU,ord(' ')); 此时KEY = ' '.类似于alt + ' '
2.如何通过WM_SYSCOMMAND改变大小:SendMessage(Handle, WM_SYSCOMMAND, SC_SIZE +  WMSZ_BOTTOM, 0);此时WMSZ_BOTTOM可以是WMSZ_TOP,WMSZ_LEFT,WMSZ_RIGHT任意一个.也用+号可以合并使用.

----------Henry 20100710 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值