模拟 MFC 的 CWnd 类的封装,出错的原因都是参数个数不匹配,而我调用的又不是 API 函数,而是类的成员函数,不知道为什么会不匹配.

unhappyless_03 2006-08-14 05:44:21
======================================CWnd.h=====================================

#ifndef CWND_H
#define CWND_H

#include<windows.h>
class CWnd
{
public:
CWnd(HWND Temp=NULL):m_hWnd(Temp){}
BOOL CreateWindowEx(
DWORD dwExStyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);

BOOL ShowWindow( HWND hWnd, int nCmdShow);
BOOL UpdateWindow( HWND hWnd );

public: HWND m_hWnd;

};

BOOL CWnd::CreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
m_hWnd=::CreateWindowEx(dwExStyle, lpClassName,lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
if(NULL==m_hWnd)
return false;
else
return true;
}

BOOL CWnd::ShowWindow( int nCmdShow)
{
return ::ShowWindow( m_hWnd, nCmdShow);
}

BOOL CWnd::UpdateWindow()
{
return ::UpdateWindow( m_hWnd) ;
}

#endif


========================================winmain.cpp================================

#include"CWnd.h"
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam,LPARAM lParam );
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
WNDCLASS wndclass;
wndclass.cbClsExtra =0;
wndclass.cbWndExtra =0;
wndclass.hbrBackground =(HBRUSH)COLOR_BACKGROUND;
wndclass.hCursor =LoadCursor(NULL,IDC_APPSTARTING);
wndclass.hIcon=NULL;
wndclass.hInstance =hInstance;
wndclass.lpszClassName =TEXT("First");
wndclass.lpszMenuName =NULL;
wndclass.style =CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc =WindowProc;

RegisterClass(&wndclass);

CWnd cwnd;
cwnd.CreateWindowEx(WS_EX_CLIENTEDGE,TEXT("First"),TEXT("模拟CWnd类的封装"),WS_OVERLAPPEDWINDOW ,100,100,200,400,NULL,NULL,hInstance,NULL);
cwnd.ShowWindow(SW_SHOWNORMAL);
cwnd.UpdateWindow ();

MSG msg;
BOOL bRet;

while( (bRet = GetMessage( &msg, cwnd.m_hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
MessageBox(cwnd.m_hWnd ,TEXT("ERROR"),TEXT("WRONG"),MB_OK);
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return (int)msg.wParam ;
}

LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch(uMsg)
{
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc;
hdc=BeginPaint(hwnd,&ps);
TextOut(hdc,0,50,TEXT("VC2005.net"), (int)strlen("VC2005.net"));
EndPaint(hwnd,&ps);
break;

case WM_LBUTTONDOWN:
MessageBox(hwnd,TEXT("mouse click"),TEXT("Myapplication"),MB_OK);
break;
case WM_CLOSE:
if(IDYES==MessageBox(hwnd,TEXT("你是否要退出程序?"),TEXT("Myapplication"),MB_YESNO))
{
DestroyWindow(hwnd);
}
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;

}
...全文
472 34 打赏 收藏 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
unhappyless_03 2006-08-16
  • 打赏
  • 举报
回复
郁闷中结贴
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
MSDN2005的地址:
ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.WIN32COM.v10.en/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues/messagesandmessagequeuesreference/messagesandmessagequeuesfunctions/getmessage.htm

在Return Value和Remarks 中间有个Warning ,那段代码就是从Show Example 抄来的.

在没看到那个Warning 前我一直当
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
是标准写法,但现在觉得这么写会不会有健壮性的隐患.
herman~~ 2006-08-15
  • 打赏
  • 举报
回复
关注
折腾_苏州 2006-08-15
  • 打赏
  • 举报
回复
循环终止了,而GetMessage()是在循环中的,也就不可能再调用到。虽然句柄无效,但也不会再用来当参数了。


------------------------------------------------------------------------------------
关键是循环没有终止,因为 GetMessage( &msg, cwnd.m_hWnd, 0, 0 )) 收不到WM_QUIT消息,
GetMessage( &msg,NULL, 0, 0 )); //这里的NULL如果传入了NULL句柄, 则表示
GetMessage retrieves messages for any window that belongs to the calling thread and thread messages posted to the calling thread via PostThreadMessage.

句柄无效和句柄为NULL 不是一个概念
DestroyWindow(hwnd)之后,句柄无效,但句柄!=NULL,这有点象指针一样,释放指针,但指针!=NULL,其实说白了,句柄也是一种指针.. (VC是开发环境当然和C++中一样了)
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
而且句柄无效和句柄为NULL 是一个概念吗?

在C++中,释放一个指针,只是释放那块内存,指针指向的地址是不变的,也就是不会为 NULL,不知VC 中是不是也这样
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
是啊,GetMessage()接到WM_QUIT时返回 0,循环终止,但是你刚开始用的cwnd.m_hWnd 做参数,……

-------------------------------

循环终止了,而GetMessage()是在循环中的,也就不可能再调用到。虽然句柄无效,但也不会再用来当参数了。



折腾_苏州 2006-08-15
  • 打赏
  • 举报
回复
是啊,GetMessage()接到WM_QUIT时返回 0,循环终止,但是你刚开始用的cwnd.m_hWnd 做参数,而非NULL, 当你WM_CLOSE时候,你把句柄摧了,再次以cwnd.m_hWnd 做参数GetMessage()肯定返回-1了,是永远也收不到WM_QUIT消息,参数改为NULL,
GetMessage retrieves messages for any window that belongs to the calling thread and thread messages posted to the calling thread via PostThreadMessage.
能接受包括主窗口句柄在类所有的消息,当然也有WM_QUIT.

至于显示出错原因,没必要了,这样的调用很少出错,MSDN上也说了
To get extended error information, call GetLastError.
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
To: muroachanf(阿远之秋去)

你的写法有问题,应改为

if (msg.message == WM_QUIT)

但结束程序后进程中还存在
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
// handle the error and possibly exit(这里可以做处理,比如exit(0),提高健壮性)

我觉得若是在此处能显示出错原因会不会更好些?

还有一点想不明白,消息队列中的消息应该是取不完的,即使你不做任何操作也会有默认的消息产生,对么?

而且GetMessage()接到WM_QUIT时返回 0 ,循环应该就终止了
muroachanf 2006-08-15
  • 打赏
  • 举报
回复
while( GetMessage( &msg, cwnd.m_hWnd, 0, 0 ))
{
if (msg == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
折腾_苏州 2006-08-15
  • 打赏
  • 举报
回复
BOOL bRet;

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit(这里可以做处理,比如exit(0),提高健壮性)
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
http://www.bc-cn.net/bbs/dispbbs.asp?boardID=55&ID=36185有人提过
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
为什么把WM_PAINT 消息处理做如下改动后,结果什么都不响应了?

case WM_PAINT:
//PAINTSTRUCT ps;
HDC hdc;
hdc=::GetDC(hwnd);
//hdc=BeginPaint(hwnd,&ps);
//CPaintDC hdc=::GetDC(hwnd);

TextOut(hdc,0,50,TEXT("VC2005.net"), (int)strlen("VC2005.net"));
//EndPaint(hwnd,&ps);
break;
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
工程设置成Use MFC in a Shared dll就行了

在哪设置的?我用的是vc2005
折腾_苏州 2006-08-15
  • 打赏
  • 举报
回复
MFC是对API的封装,反之也可以用
#include <AFXWIN.H>
工程设置成Use MFC in a Shared dll就行了

但你的不行,你定义了CWnd和MFC中的CWnd冲突
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
为什么在MFC中可以用API函数,反之不行?
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
MFC 的类是不是像我那样,把API 的函数封装进来?
折腾_苏州 2006-08-15
  • 打赏
  • 举报
回复
CPaintDC


The CPaintDC class is a device-context class derived from CDC.

Header file: Afxwin.h
折腾_苏州 2006-08-15
  • 打赏
  • 举报
回复
你既然模拟 MFC 的 CWnd 类的封装,也不能再引入#include <AFXWIN.H>了中的MFC类了
否则会引起冲突.......

要么学它的CPaintDC也来个封装
unhappyless_03 2006-08-15
  • 打赏
  • 举报
回复
我用的是全局的,SDK 也有吧,MSDN 上都看的到
折腾_苏州 2006-08-15
  • 打赏
  • 举报
回复
CPaintDC 是MFC里的东西
加载更多回复(14)

16,550

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧