Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1614601
  • 博文数量: 441
  • 博客积分: 20087
  • 博客等级: 上将
  • 技术积分: 3562
  • 用 户 组: 普通用户
  • 注册时间: 2006-06-19 15:35
文章分类

全部博文(441)

文章存档

2014年(1)

2012年(1)

2011年(8)

2010年(16)

2009年(15)

2008年(152)

2007年(178)

2006年(70)

分类: C/C++

2006-11-15 11:01:42

看了候杰的深入潜出MFC中的第一章,有这样一个Win32程序,Geneirc程序:
//以下是候杰的深入浅出MFC中的Generic程序
#include
#include "resource.h"
#include "generic.h"

HINSTANCE _hInst;
HWND _hWnd;

char _szAppName[] = "Generic";
char _szTitle[] = "Generic Sample Application";

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;

UNREFERENCED_PARAMETER(lpCmdLine);

if (!hPrevInstance)
if (!InitApplication(hInstance))
return (FALSE);

if (!InitInstance(hInstance, nCmdShow))
return (FALSE);

while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (msg.wParam);
}

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, "jjhouricon");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = 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);
return (TRUE);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;

switch (message) {
case WM_COMMAND:

wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);

switch (wmId) {
case IDM_ABOUT:
DialogBox(_hInst,
"AboutBox",
hWnd,
(DLGPROC)About
);
break;

case IDM_EXIT:
DestroyWindow (hWnd);
break;

default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0);
}

LRESULT CALLBACK About(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);

switch (message) {
case WM_INITDIALOG:
return (TRUE);

case WM_COMMAND:
if (LOWORD(wParam) == IDOK
|| LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, TRUE);
return (TRUE);
}
break;
}
return (FALSE); // FALSE ?
}

我把它改装成以下的形式:
// filename : generic.c

#include
#include "generic.h"
#include "resource.h"

HINSTANCE _hInst;
HWND _hWnd;

char _szAppName[] = "Generic";
char _szTitle[] = "Generic Sample Application";

LONG OnCommand(HWND, UINT, WPARAM, LPARAM);
LONG OnDestroy(HWND, UINT, WPARAM, LPARAM);
LONG OnAbout(HWND, UINT, WPARAM, LPARAM);
LONG OnExit(HWND, UINT, WPARAM, LPARAM);
LONG OnInitDialog(HWND, UINT, WPARAM, LPARAM);
LONG OnEndDialog(HWND, UINT, WPARAM, LPARAM);

struct MSGMAP_ENTRY
{
UINT nMessage;
LONG (*pfn)(HWND, UINT, WPARAM, LPARAM);
};

#define dim(x) (sizeof(x) / sizeof(x[0]))

struct MSGMAP_ENTRY _messageEntries[] =
{
WM_COMMAND, OnCommand,
WM_DESTROY, OnDestroy,
WM_INITDIALOG, OnInitDialog,
};

struct MSGMAP_ENTRY _commandEntries[] =
{
IDM_ABOUT, OnAbout,
IDM_EXIT, OnExit,
IDOK, OnEndDialog,
IDCANCEL, OnEndDialog,
};


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
MSG msg;

UNREFERENCED_PARAMETER(lpCmdLine);

if ( !hPrevInstance )
if ( !InitApplication(hInstance) )
return FALSE;

if ( !InitInstance(hInstance, nShowCmd) )
return FALSE;

while ( GetMessage(&msg, NULL, 0, 0 ) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}


BOOL InitApplication(HANDLE hInstance)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(hInstance, "jjhouricon");
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "GenericMenu";
wc.lpszClassName = _szAppName;

return RegisterClass(&wc);
}

BOOL InitInstance(HANDLE 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);

return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int i;
for ( i=0; i {
if ( uMsg == _messageEntries[i].nMessage )
return ((*_messageEntries[i].pfn)(hWnd, uMsg, wParam, lParam));
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

LONG OnCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int i;
for ( i=0; i {
if ( LOWORD(wParam) == _commandEntries[i].nMessage )
{
return ((*_commandEntries[i].pfn)(hWnd, uMsg, wParam, lParam));
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

LONG OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}

LONG OnAbout(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DialogBox(_hInst, "AboutBox", hWnd, (DLGPROC)About);
return 0;
}

LONG OnExit(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DestroyWindow(hWnd);
return 0;
}

LONG OnInitDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return TRUE;
}

LONG OnEndDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
EndDialog(hWnd, TRUE);
return 0;
}

LRESULT CALLBACK About(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int i;
for ( i=0; i {
if ( uMsg == _messageEntries[i].nMessage )
return ((*_messageEntries[i].pfn)(hWnd, uMsg, wParam, lParam));
}
return FALSE;
}

但是问题出来了,当我按关于对话框About上面的那个OK按钮的时候,整个应用程序都结束了,也就是说,那个OK按钮按下去,不仅仅结束了关于对话框,而且结束了主对话框,我找了半天都没有找出问题的所在,于是在csdn上发帖子,发了2个小时还是没有人能解决,估计是帖子太长了,都懒得看,于是我在vckbase.com的论坛上发帖子,半个小时就解决了问题,看来还是vckbase.com上的高手更加专业,也更加倾向于解决问题呀。
问题的解决方法如下:

LONG OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0);
return 0;
}
改为
LONG OnDestroy(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if ( hWnd == _hWnd )
        PostQuitMessage(0);
    return 0;
   
}
_hWnd为主窗口句柄, hWnd为传过来的子窗口(即About对话框)的句柄,判断一下传过来的是否主对话框的句柄,不是的话,就不结束。据愚人之见以及vckbase.com上的高手的说法,在EndDialog中,系统会产生一个WM_DESTROY消息,由于没有判断是否是主窗口的句柄,所以就直接退出了应用程序。

通过这个问题的解决,我意识到,在Message Based和Event Driven的编程中一定要以Message和Event作为核心,上面的这个问题就说明了这一点。
阅读(1343) | 评论(6) | 转发(0) |
给主人留下些什么吧!~~