今天修改了一下CmnHdr.h的chHANDLE_DLGMSG宏,编译通过了。
消息处理宏HANDLE_MSG只能用于窗口过程,不能用于对话框过程。首先看窗口过程和对话框过程的差别:
1.窗口过程返回LRESULT(即LONG);对话框过程返回BOOL(即int,不过VC.NET自动生成的代码为LRESULT。);
2.窗口过程处理完一条消息后,一般返回0;而对话框过程一般处理完一条消息后,返回TRUE,如果不处理则返回FALSE,由对话框管理器执行默认操作。但以下几条消息例外,对它们处理完后要返回特定值:
WM_CTLCOLORMSGBOX
...
WM_INITDIALOG
所以设计用于窗口过程的HANDAL_WM_*一般返回0,如把它用于对话框过程,反而表示对话框过程未处理由系统自行默认操作。改正的方法是改为返回TRUE即可。但是对于上边所说的要返回特定值得消息,返回值要保持不变。
知道了上边的区别,我们就可以设计专用与对话框过程的消息处理宏了。
作者的设计是利用了SetDlgMsgResult,比较简洁,但初学者就头疼了:
// The normal HANDLE_MSG macro in WindowsX.h does not work properly for dialog
// boxes because DlgProc return a BOOL instead of an LRESULT (like
// WndProcs). This chHANDLE_DLGMSG macro corrects the problem:
#define chHANDLE_DLGMSG(hwnd, message, fn) case (message): return (SetDlgMsgResult(hwnd, uMsg, HANDLE_##message((hwnd), (wParam), (lParam), (fn))))*/
以下是我的第二种设计
#define chHANDLE_DLGMSG(hwnd, message, fn)case (message): return(( (message) == WM_CTLCOLORMSGBOX || (message) == WM_CTLCOLOREDIT || (message) == WM_CTLCOLORLISTBOX || (message) == WM_CTLCOLORBTN || (message) == WM_CTLCOLORDLG || (message) == WM_CTLCOLORSCROLLBAR || (message) == WM_CTLCOLORSTATIC || (message) == WM_COMPAREITEM || (message) == WM_VKEYTOITEM || (message) == WM_CHARTOITEM || (message) == WM_QUERYDRAGICON || (message) == WM_INITDIALOG ) ? HANDLE_##message((hwnd), (wParam), (lParam), (fn)):(HANDLE_##message((hwnd), (wParam), (lParam), (fn)),TRUE))
另外还不习惯用Message Crackers,所以趁有空就把程序改了一下。下面是ErrorShow的api简单实现,环境是vc.net2003:
// ErrorShow.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "ErrorShow.h"
//#define ESM_POKECODEANDLOOKUP (WM_USER + 100)
// 此代码模块中包含的函数的前向声明:
//LRESULT CALLBACK Dlg_Proc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
//DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_ERRORSHOW),NULL,(DLGPROC)Dlg_Proc,_ttoi(lpCmdLine));
DialogBox(hInstance,MAKEINTRESOURCE(IDD_ERRORSHOW),NULL,(DLGPROC)Dlg_Proc);
return 0;
}
//对话框的消息处理程序。
//LRESULT CALLBACK Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
BOOL CALLBACK Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
//SendMessage(hwnd,WM_SETICON,ICON_BIG,
//(LPARAM)LoadIcon((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
//MAKEINTRESOURCE(IDI_ERRORSHOW)));
SendMessage(hwnd,WM_SETICON,ICON_SMALL,
(LPARAM)LoadIcon((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),
MAKEINTRESOURCE(IDI_ERRORSHOW)));
SendMessage(GetDlgItem(hwnd,IDC_ERRORCODE),EM_LIMITTEXT,5,0);
/ /SendMessage(hwnd,ESM_POKECODEANDLOOKUP,lParam,0);
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDCANCEL:
EndDialog(hwnd, LOWORD(wParam));
break;
case IDC_ALWAYSONTOP:
SetWindowPos(hwnd, IsDlgButtonChecked(hwnd, IDC_ALWAYSONTOP)
? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
break;
case IDC_ERRORCODE:
EnableWindow(GetDlgItem(hwnd, IDOK),GetWindowTextLength((HWND)lParam) > 0);
break;
case IDOK:
// Get the error code
DWORD dwError = GetDlgItemInt(hwnd, IDC_ERRORCODE, NULL, FALSE);
HLOCAL hlocal = NULL; // Buffer that gets the error message string
// Get the error code's textual description
BOOL fOk = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language,
(PTSTR) &hlocal, 0, NULL);
/* if (!fOk) {
// Is it a network-related error?
HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL,
DONT_RESOLVE_DLL_REFERENCES);
if (hDll != NULL) {
FormatMessage(
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM,
hDll, dwError, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(PTSTR) &hlocal, 0, NULL);
FreeLibrary(hDll);
}
}*/
if (hlocal != NULL) {
SetDlgItemText(hwnd, IDC_ERRORTEXT, (PCTSTR) LocalLock(hlocal));
LocalFree(hlocal);
} else {
SetDlgItemText(hwnd, IDC_ERRORTEXT, TEXT("Error number not found."));
}
break;
}
}
return FALSE;
}