今天继续折腾那个List Box控件,发现一个问题,当对话框出来之后,被主窗体给刷屏了,不能得到子窗体的句柄。后经仔细调试,发现一些端倪。首先在调用 DialogBox函数时 ,所生成的Dialog(我这里的Dialog面板里有一个Edit控件 两个按钮控件 和一个List Box控件)依次产生的消息队列如下所示: WM_SETFONT 0x0030 设置字体 WM_INITDIALOG 0x0110 初始化Dialog WM_WINDOWPOSCHANGING 0x0046 窗体大小 位置等转变的消息 WM_NCACTIVATE 0x0086 改变一个非工作区域 sent to a window when its nonclient area needs to be changed to indicate an active or inactive state. WM_ACTIVATE 0x0006 让你窗体无效 并激活子窗体 WM_COMMAND 0x0111 (HIWORD(WPARAM))->LBN_SETFOCUS(4) ->LBN_KILLFOCUS(5) 消息命令 ListBox WM_USER 0x0400 用户自定义消息 WM_NCACTIVATE 0x0086 WM_SHOWWINDOW 0x0018 显示窗体 WM_WINDOWPOSCHANGING 0x0046 WM_NCPAINT 0x0085 The WM_NCPAINT message is sent to a window when its frame must be painted. WM_ERASEBKGND 0x0014 清楚窗口背景 WM_WINDOWPOSCHANGED 0x0047 WM_GETICON 0x007F 3次 The WM_GETICON message is sent to a window to retrieve a handle to the large or small icon associated with a window WM_NCCALCSIZE 0x0083 计算机窗体大小尺寸 WM_MOVE 0x0003 移动 WM_SIZE 0x0005 改变大小 WM_PAINT 0x000F 绘制窗体 WM_CTLCOLORBTN 0x0135 绘制按钮的颜色 WM_CTLCOLORLISTBOX 0x0134 绘制Listbox的颜色 WM_CTLCOLOREDIT 0x0133 绘制Edit的颜色 WM_POWERBROADCAST 0x0218 broadcast to an application to notify it of power-management events while(1) 一直循环以下的两个消息 WM_NCACTIVATE 0x0086 WM_WINDOWPOSCHANGING 0x0046
代码如下:
BOOL CALLBACK ListBoxTest(HWND hWnd,UINT message , WPARAM wParam, LPARAM lParam) { int wmId = LOWORD(wParam ); int wmEvent = HIWORD(wParam) ; int i ; HDC hDc ; PAINTSTRUCT ps ; HWND hListBox ; switch(message) { case WM_INITDIALOG: hListBox = GetDlgItem(hWnd,IDC_LIST_TEST) ; for(i = 0; MyData[i].Name[0] != 0 ; i++) { SendMessage(hListBox,LB_ADDSTRING,0,(LPARAM)MyData[i].Name) ; SendMessage(hListBox,LB_SETITEMDATA, i ,(LPARAM)i) ; } SetFocus(hListBox); return (TRUE) ; case WM_PAINT: hDc = BeginPaint(hWnd,&ps) ; //MSGPRINT(_T("Print")) ; EndPaint(hWnd,&ps); break ; case LB_ADDFILE: break ; case WM_COMMAND: switch(wmId) { case IDC_LIST_TEST: switch(wmEvent) { case LBN_SELCHANGE: //MSGPRINT(_T("LBN_SELCHANGE")); break ; case LBN_DBLCLK: //MSGPRINT(_T("LBN_DBLCLK")); break ; case LBN_SETFOCUS: //MSGPRINT(_T("LBN_SETFOCUS")) ; break ; case LBN_KILLFOCUS: //MSGPRINT(_T("LBN_KILLFOCUS")) ; break ; } return FALSE ; break ; case IDOK: MSGPRINT(_T("IDOK")); EndDialog(hWnd,0) ; return TRUE; break ; case IDCANCEL: MSGPRINT(_T("IDCANCEL")); EndDialog(hWnd,0) ; return TRUE ; break ; } } return FALSE; }
如果最后返回TRUE那么窗体的着色会很有问题,Dialog的颜色和背景颜色完全一样,导致不能看到一个窗体的存在,所以这里必须返回FALSE, MSDN作出的解释如下:Typically, the dialog box procedure should return TRUE if it processed the message, and FALSE if it did not. If the dialog box procedure returns FALSE, the dialog manager performs the default dialog operation in response to the message. 意即,如果这个窗体想处理哪个消息就返回TRUE,如果不想处理这个消息就返回FALSE,所以在最后应该返回False,即默认不处理那些消息而只算WM_INITDIALOG 和其它一些IDOK IDCANCEL的消息。 If the dialog box procedure processes a message that requires a specific return value, the dialog box procedure should set the desired return value by calling SetWindowLong(hwndDlg, DWL_MSGRESULT, lResult) immediately before returning TRUE. Note that you must call SetWindowLong immediately before returning TRUE; doing so earlier may result in the DWL_MSGRESULT value being overwritten by a nested dialog box message.
这个嘛 靠 英文 烂!勉勉强强 如果窗体在处理一个消息时需要显示地返回一个值,那这个窗体应该在返回TRUE前调用SetWindoLong(hWndDlg,DWL_MSGRESULT,lpResult)函数更改想要返回的值.切记一定要马上调用该函数在返回TRUE之前,尽可能早地通过DWL_MSGRESULT去改写真正的Result,by a nested dialog box message. 他妈的这句怎么翻译?
现在都开始怀疑弄这些消息有什么用,用MFC肯定是一个更好的选择。在List Box里增加和删除内容都是太烦了,都是通过SendMessage来完成的。不知道能坚持学到什么时候。
|