使用WNDCLASS创建的窗口没写消息循环,如何取消息的?

380 人浏览 | 时间: 2020-05-23 11:26:38 | 作者: intel0011

对话框初始化过程中使用WNDCLASS创建的窗口,但并没有写消息循环,那么这个窗口是如何取出消息队列中的消息(非消息队列中的消息很容易理解,直接发给窗口过程)

Resource.h

#define DLG_MAIN 1000
#define ICO_MAIN 1103

XPStyle.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
   <dependentAssembly>
      <assemblyIdentity
         type="win32"
         name="Microsoft.Windows.Common-Controls"
         version="6.0.0.0"
         processorArchitecture="x86"
         publicKeyToken="6595b64144ccf1df"
         language="*" />
   </dependentAssembly>
</dependency>
</assembly>

HelloWin.rc

#include <WinRes.h>
#include "Resource.h"

DLG_MAIN DIALOGEX 160, 160, 236, 185
STYLE DS_CENTER | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "对话框模板"
FONT 9, "宋体"
BEGIN
   DEFPUSHBUTTON "测试",IDOK,107,163,50,14
   DEFPUSHBUTTON "退出",IDCANCEL,177,163,50,14
END

1        RT_MANIFEST "XPStyle.manifest"
ICO_MAIN ICON        "bulbs.ico" //可自己任意找一个

STRINGTABLE DISCARDABLE 
{
   IDOK     "WS_EX_CONTEXTHELP测试1" 
   IDCANCEL "WS_EX_CONTEXTHELP测试2" 
}

HelloWin.c

//*
#define UNICODE
#define _UNICODE
//*/
#include <Windows.h>
#include <tchar.h>
#include <commctrl.h>
#include "Resource.h"

#pragma comment(lib, "gdi32")
#pragma comment(lib, "user32")
#pragma comment(lib, "comctl32")

#pragma comment(linker, "/subsystem:windows,5.1.2600")

#define WM_USER_SETTEXT    (WM_USER + 10) //wParam : Pointer to the TCHAR string; lParam : NULL
#define WM_USER_SHOWWINDOW (WM_USER + 11) //wParam : mouse.x; lParam : mouse.y

// Message handler for MyToolTipWindow
LRESULT CALLBACK MyToolTipProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   static TCHAR szToDisp[1024];
   
   switch (message)
   {
   case WM_LBUTTONDOWN:
   case WM_RBUTTONDOWN:
   case WM_KEYDOWN:
   case WM_KILLFOCUS:
      ShowWindow(hwnd, FALSE);
      return 0;
   case WM_PAINT:
      {
         RECT rect;
         PAINTSTRUCT ps;
         HDC hdc = BeginPaint(hwnd, &ps);
         GetWindowRect(hwnd, &rect);
         rect.right = rect.right - rect.left;
         rect.bottom = rect.bottom - rect.top;
         rect.top = 0;
         rect.left = 0;
         SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
         DrawText(hdc, szToDisp, lstrlen(szToDisp), &rect, DT_LEFT | DT_WORDBREAK);
         SelectObject(hdc, GetStockObject(SYSTEM_FONT));
         EndPaint(hwnd, &ps);
      }
      return 0;
   case WM_USER_SETTEXT:
      lstrcpy(szToDisp, (TCHAR *)wParam);
      return 0;
   case WM_USER_SHOWWINDOW:
      {
         UINT iScreenWidth;
         UINT iXPos;
         HDC hdc;
         DWORD dwRtn;
         hdc = GetDC(hwnd);
         SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
         dwRtn = GetTabbedTextExtent(hdc, szToDisp, lstrlen(szToDisp), 0, NULL);
         SelectObject(hdc, GetStockObject(SYSTEM_FONT));
         ReleaseDC(hwnd, hdc);
         iScreenWidth = GetSystemMetrics(SM_CXFULLSCREEN);
         iXPos = wParam + LOWORD(dwRtn) + 4 > iScreenWidth ? iScreenWidth - LOWORD(dwRtn) - 4 : wParam;
         MoveWindow(hwnd, iXPos, lParam + 21, LOWORD(dwRtn) + 4, HIWORD(dwRtn) + 3, FALSE);
         ShowWindow(hwnd, TRUE);
      }
      return 0;
   case WM_DESTROY: //sent to the window procedure of the window being destroyed after the window is removed from the screen
         PostQuitMessage(0);
         return 0;
   }
   return DefWindowProc(hwnd, message, wParam, lParam);
}

LRESULT CALLBACK ProcDlgMain(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) 
{
   static HWND hwndToolTip;

   UNREFERENCED_PARAMETER(lParam);

   switch (message)
   {
   case WM_INITDIALOG:
      SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(ICO_MAIN)));
      SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(ICO_MAIN)));
      {
         DWORD dwStyle = GetWindowLong(hwndDlg, GWL_EXSTYLE);
         SetWindowLong(hwndDlg, GWL_EXSTYLE, dwStyle | WS_EX_CONTEXTHELP);
      }
      {
         WNDCLASS wndclass;
         wndclass.style = CS_HREDRAW | CS_VREDRAW;
         wndclass.lpfnWndProc = MyToolTipProc;
         wndclass.cbClsExtra = 0;
         wndclass.cbWndExtra = 0;
         wndclass.hInstance = GetModuleHandle(NULL);
         //wndclass.hIcon = LoadIcon(GetModuleHandle(NULL), (LPCTSTR)ICO_MAIN);
         wndclass.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(ICO_MAIN));
         wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
         wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
         wndclass.lpszMenuName = NULL;
         wndclass.lpszClassName = TEXT("MyToolTipWindow");
         RegisterClass (&wndclass);
         hwndToolTip = CreateWindow(TEXT("MyToolTipWindow"), TEXT(""),
                                    WS_POPUP | WS_BORDER, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                                    CW_USEDEFAULT, hwndDlg, (HMENU)NULL, GetModuleHandle(NULL), NULL);
      }
      break;
   case WM_COMMAND:
      switch (LOWORD(wParam))
      {
      //系统对WM_CLOSE消息的默认处理和对Esc键的默认处理是相同的
      case IDCANCEL:
         DestroyWindow(hwndToolTip);
         EndDialog(hwndDlg, 0);
         break;
      case IDOK:
         MessageBox(hwndDlg, TEXT("Test Message"), TEXT("Test"), MB_OK);
         break;
      }
      break;
   case WM_HELP:
      {      
         LPHELPINFO lphi = (LPHELPINFO)lParam;
         if (lphi->iContextType == HELPINFO_WINDOW)
         {
            TCHAR szDisp[256];
            memset(szDisp, 0, sizeof(szDisp));
            LoadString(GetModuleHandle(NULL), lphi->iCtrlId, szDisp, 255);
            #if 0
            SendMessage(hwndToolTip, WM_USER_SETTEXT, (WPARAM)(szDisp), 0); //SendMessage不需要消息循环
            if (0 == lstrlen(szDisp)) break;
            SendMessage(hwndToolTip, WM_USER_SHOWWINDOW, lphi->MousePos.x, lphi->MousePos.y);
            #else
            PostMessage(hwndToolTip, WM_USER_SETTEXT, (WPARAM)(szDisp), 0); //XP和Win10下使用PostMessage也OK,但hwndToolTip并没有消息循环呀
            if (0 == lstrlen(szDisp)) break;
            PostMessage(hwndToolTip, WM_USER_SHOWWINDOW, lphi->MousePos.x, lphi->MousePos.y);
            #endif
         }
      }
      break;      
   default:
      return FALSE;
   }
   return TRUE;
}

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow)
{
   //InitCommonControls();
   {
      INITCOMMONCONTROLSEX InitCtrls;
      InitCtrls.dwSize = sizeof(InitCtrls);
      InitCtrls.dwICC = ICC_BAR_CLASSES;
      InitCommonControlsEx(&InitCtrls);
   }
   DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, ProcDlgMain, 0);
   return 0; 
}


标注
评论
站内搜
百度搜
传送到手机
手机扫码,识别文字,完成传送x
加载中...
标注内容x
加载中...
添加标注x
收藏 0 点赞 0
  • codexia 2020-05-23 11:34:30

    DialogBoxParam函数用CreateWindowEx函数创建对话框。然后把一个WM_INITDIALOGG消息传递到对话框过程。如果模板指定DS_SETFONT类型,DialogBoxParam函数把一个WM_SETFONT消息传递到对话框过程。(不管模板是否指定WS_VISIBLE类型),函数显示对话框使拥有窗口失效,且为对话框启动它本身的消息循环来检取和传递消息。当对话框应用程序调用EndDialog函数时,DialogBoxParam函数清除对话框中止消息循环;使拥有窗口生效(如果以前有效),且返回函数EndDialog的调用中的nReSUlt参数。
    0回复

相关阅读