winx的你好
#define WINX_USE_APPMODULE
#include <winx.h>
class CHelloMainFrame: public winx::MainFrame<CHelloMainFrame>
{
WINX_CLASS("CHelloMainFrame");
public :
void OnPaint(HWND hWnd)
{
winx::PaintDC dc(hWnd);
dc.TextOut(1,1,_T("你好,WINX!"));
}
};
winx::CAppModule _Module;
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
CAppModuleInit module;
CHelloMainFrame::RegisterClass();
CHelloMainFrame wndMain;
wndMain.Create(NULL,_T("你好"));
return module.Run();
}
编程模型
注册窗口类
WINX
中RegisterClass
是要主动调用的.
以下这些宏与WINX
的RegisterClass
有关:
WINX_CLASS/WINX_CLASS_EX(类)
,WINX_CLASS_STYLE(网格)
,WINX_DEFAULT_BKGND/WINX_DEFAULT_COLOR/WINX_DEFAULT_BRUSH(背景/颜色/刷)
,WINX_DEFAULT_CURSOR/WINX_DEFAULT_SYSCURSOR(光标)
,它们分别对应Windows
窗口类(WNDCLASSEX)
中的lpszClassName
,style
,hbrBackground
,hCursor
等成员.
用WINX_CLASS
指定窗口类
名,其他宏的用法
完全一致.例如,默认鼠标光标
是箭头(IDC_ARROW)
,就很容易用IDC_IBEAM
改为像Edit
控件一样:
class CHelloMainFrame : public winx::MainFrame<CHelloMainFrame>
{
WINX_DEFAULT_SYSCURSOR(IDC_IBEAM);
... //默认系统光标.
};
初化类
大致有:
类 | 作用 |
---|---|
CComAppInit | COM 初化类,即CoInitialize/CoUninitialize 对 |
COleAppInit | OLE 初化类,即OleInitialize/OleUninitialize 对. |
CDebugAppInit | 启动内存泄漏调试(仅Debug 版本,Release 版本为空类). |
CComModuleInit | CComModuleInit/Term . |
CAppModuleInit | CAppModuleInit/Term . |
GdiplusAppInit | GdiplusStartup/GdiplusShutdown. |
消息循环
借用WTL
的CMessageLoop::Run
,藏在:CAppModuleInit
里面.
class CAppModuleInit : public WTL::CMessageLoop
{
public :
CAppModuleInit(
_ATL_OBJMAP_ENTRY*p=NULL,
HINSTANCE hInst=GetThisModule(),
const GUID*plibid=NULL)
{
_Module.Init(p, hInst, plibid);
_Module.AddMessageLoop( this );
}
~ CAppModuleInit()
{
_Module.Term();
}
};
窗口过程
template <class WindowClass,class HandleClass=DefaultWindowHandle>
class Window
{
public :
static LRESULT CALLBACK WindowProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WindowClass*pWnd=(WindowClass*)WindowMap::GetWindow(hWnd);
if(pWnd==NULL){
if(message!=WM_NCCREATE)
return pWnd->InternalDefault(hWnd,message,wParam,lParam);
LPCREATESTRUCT lpCS=(LPCREATESTRUCT)lParam;
if(lpCS->lpCreateParams){
pWnd=(WindowClass*)lpCS->lpCreateParams;
lpCS->lpCreateParams=NULL;
}else{
if(WindowClass::StackWindowObject){
WINX_ASSERT( " WindowClass::StackWindowObject - unexpected! " );
return FALSE;
}else{
pWnd=WINX_NEW(WindowClass);
}
}
WindowMap::SetWindow(hWnd, pWnd);
}
return pWnd->ProcessMessage(hWnd,message,wParam,lParam);
}
};
WindowMap::GetWindow/SetWindow
是什么?
UserData
建立窗口句柄(hWnd)
到窗口对象(pWnd)
的映射.
还可用SetProp/GetProp
或自己实现的其他方式建立映射.前者是WINX
默认选择.
简单分析
一下,这些方式的利弊.
通过HashMap
建立映射,问题在于,其他DLL
如何取到该HashMap
对象?会导致bug
或者强耦合结构.
用窗口的UserData
建立映射,问题在于如果已占用UserData
怎么办?机制上有点不安全.
使用SetProp/GetProp
建立映射,性能比UserData
方式慢,但极其安全.
WindowClass::StackWindowObject
,放在栈
上的窗口.
最后,pWnd->ProcessMessage(hWnd,message,wParam,lParam)
处理处理消息.
ProcessMessage
是消息机制的核心
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现