使用背景
利用VS创建空项目,使用WinMain入口构建代码创建一个win32窗口时,运行老是不显示窗口,调试发现程序在CreateWindow时老是产生失败结果:
就是上图,_hWnd获取CreateWindow的结果,这里结果一直为空
问题原因
检查代码发现在WndProc中有一处问题
红色圈起来的地方,比较运算写错了(失误讨打)
谨以此问题告诫所有在踏入程序海洋的同胞
下面附上完整代码
代码引用自:《深入浅出MFC(侯捷)》
Generic.h
#ifndef _INCLUDE_WIN32_MLTTHRDPRIORITY_H
#define _INCLUDE_WIN32_MLTTHRDPRIORITY_H
BOOL InitApplication(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
LONG OnAbout(HWND, UINT, WPARAM, LPARAM);
LONG OnCommand(HWND, UINT, WPARAM, LPARAM);
LONG OnExit(HWND, UINT, WPARAM, LPARAM);
LONG OnDestroy(HWND, UINT, WPARAM, LPARAM);
LONG OnResume(HWND, UINT, WPARAM, LPARAM);
#endif //_INCLUDE_WIN32_MLTTHRDPRIORITY_H
Generic.c
#include <windows.h>
#include "Generic.h"
#include "resource.h"
HINSTANCE _hInst; //应用程序句柄
HWND _hWnd; //窗口句柄
char _szAppName[] = "Generic"; //应用程序类名
char _szTitle[] = "Sample of Generic(MultiThread)"; //应用程序标题名
//消息与方法结构
struct MSGMAP_ENTRY{
UINT nMessage; //消息(数据)
LONG (*pfn)(HWND, UINT, WPARAM, LPARAM); //指向执行消息的函数指针(处理数据的方法)
};
#define dim(x) (sizeof(x)/sizeof(x[0])) //声明获取消息映射入口的尺寸
//模拟消息映射(防MFC)
struct MSGMAP_ENTRY _messageEntries[] = {
WM_COMMAND, OnCommand,
WM_DESTROY, OnDestroy,
};
//消息映射(WM_COMMAND)
struct MSGMAP_ENTRY _commandEntries[] = {
IDM_ABOUT, OnAbout,
IDM_EXIT, OnExit,
IDM_RESUME, OnResume,
};
HANDLE _hThread[5]; //全局变量_线程句柄数组
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
UNREFERENCED_PARAMETER(lpCmdLine); //(不考虑临界参数)避免编译时的警告
if (!hPrevInstance)
if (!InitApplication(hInstance))
return 0;
if (!InitInstance(hInstance, nCmdShow))
return 0;
while(TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW; //窗口样式
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0; //窗口类无扩展
wc.cbWndExtra = 0; //窗口无扩展
wc.hInstance = hInstance; //窗口依赖的应用程序句柄
wc.hIcon = LoadIcon(hInstance, "Cheng"); //窗口图标
wc.hCursor = LoadCursor(NULL, IDC_ARROW); //窗口光标
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //窗口画刷
wc.lpszMenuName = "GenericMenu"; //窗口菜单资源名
wc.lpszClassName = _szAppName; //窗口类名
return (RegisterClass(&wc));
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
_hInst = hInstance;
_hWnd = CreateWindow(_szAppName, _szTitle, //窗口类名(必需与注册类名保持一致)和标题
WS_OVERLAPPEDWINDOW, //窗口风格(重叠窗口)
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, //窗口位置和尺寸
NULL, NULL, //无父窗口,无菜单
hInstance, //窗口依赖的应用程序句柄
NULL //预留
);
if (!_hWnd)
{
return FALSE;
}
ShowWindow(_hWnd, nCmdShow); //显示窗口
UpdateWindow(_hWnd); //绘制用户区,发送WM_PAINT消息
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
int i;
for (i = 0; i < dim(_messageEntries); i++)
{
if (nMessage == _messageEntries[i].nMessage)
{
return ((*_messageEntries[i].pfn)(hWnd, nMessage, wParam, lParam));
}
}
return (DefWindowProc(hWnd, nMessage, wParam, lParam));
}
LRESULT CALLBACK About(HWND hDlg, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam); //(不考虑临界参数)避免编译时的警告
switch(nMessage)
{
case WM_INITDIALOG:
return (TRUE); //TRUE 表示处理了这个消息
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE); //关闭对话框
return (TRUE); //TRUE 表示处理了这个消息
}
break;
}
return (FALSE); //表示没有处理这个消息
}
LONG OnCommand(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
int i;
for (i = 0; i < dim(_commandEntries); i++)
{
if (LOWORD(wParam) == _commandEntries[i].nMessage)
{
return ((*_commandEntries[i].pfn)(hWnd, nMessage, wParam, lParam));
}
}
return DefWindowProc(hWnd, nMessage, wParam, lParam);
}
//
LONG OnAbout(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
DialogBox(_hInst, //对话框依赖的应用程序句柄
"AboutBox", //对话框资源名
hWnd, //对话框父窗口句柄
(DLGPROC)About //对话框函数
);
return (TRUE);
}
LONG OnExit(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
DestroyWindow(hWnd);
return 0;
}
LONG OnDestroy(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}
LONG OnResume(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam)
{
return 0;
}
resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Generic.rc
#define IDM_NEW 25001
#define IDM_OPEN 25002
#define IDM_SAVE 25003
#define IDM_SAVEAS 25004
#define IDM_PRINT 25005
#define IDM_PRINTSETUP 25006
#define IDM_EXIT 25007
#define IDM_UNDO 25008
#define IDM_CUT 25009
#define IDM_COPY 25010
#define IDM_PASTE 25011
#define IDM_LINK 25012
#define IDM_LINKS 25013
#define IDM_HELPCONTENTS 25014
#define IDM_HELPSEARCH 25015
#define IDM_HELPHELP 25016
#define IDM_ABOUT 25017
#define IDM_RESUME 25018
#define IDM_DELETE 25019
// 新对象的下一组默认值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Generic.rc
#include "resource.h"
Cheng ICON DISCARDABLE "Cheng.ico"
GenericMenu MENU DISCARDABLE
BEGIN
POPUP "系统(&T)"
BEGIN
MENUITEM "退出(&X)" IDM_EXIT
END
POPUP "文件(&F)"
BEGIN
MENUITEM "新建(&N)" IDM_NEW
MENUITEM "打开(&O)" IDM_OPEN
MENUITEM "保存(&S)" IDM_SAVE
MENUITEM "另存为(&A)" IDM_SAVEAS
MENUITEM SEPARATOR
MENUITEM "打印(&P)" IDM_PRINT
MENUITEM "打印设置(&R)" IDM_PRINTSETUP
END
POPUP "编辑(&E)"
BEGIN
MENUITEM "撤销(&Z\tCtrl+Z)" IDM_UNDO
MENUITEM SEPARATOR
MENUITEM "剪切(&t\tCtrl+X)" IDM_CUT
MENUITEM "复制(&C\tCtrl+C)" IDM_COPY
MENUITEM "粘贴(&V\tCtrl+V)" IDM_PASTE
MENUITEM "删除(&D)" IDM_DELETE
END
POPUP "操作(&P)"
BEGIN
MENUITEM "启动(&R)" IDM_RESUME
END
POPUP "帮助(&H)"
BEGIN
MENUITEM "关于(&B)" IDM_ABOUT
END
END