应用程序类型 |
描述 |
---|---|
sdi |
单文本 |
多线程sdi |
一进程,多窗口 |
mdi |
框架内,多窗口 |
对话 |
基于对话框 |
多线程sdi新建sdi
窗口,应用程序,都可作com
服务器.钢筋条
是工具栏
等的容器
.命令栏
可把窗口
加至工具栏中.有了rebar
,按工具栏
实现工具条和菜单
.这样,菜单也有关联图标.
可选视:
视 |
描述 |
---|---|
简单窗口 |
处理WM_PAINT ,直接画时 . |
表单 |
具对话框模版 ,应用程序操作 |
列表框 |
可加串 . |
编辑框 |
给你编辑 |
列表视 |
如控制面板
|
树视 |
用于层级关系, |
富文本 |
富文本 |
程序线程
同atl
,有个_Module
,为CAppModule/CServerAppModule(com)
实例.应用程序具1/多
ui线程.单ui
调用全局Run
.
int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
CMessageLoop theLoop;
_Module.AddMessageLoop(&theLoop);
CMainFrame wndMain;
if (wndMain.CreateEx() == NULL)
{
ATLTRACE(_T("创建主窗口失败"));
return 0;
}
wndMain.ShowWindow(nCmdShow);
int nRet = theLoop.Run();
_Module.RemoveMessageLoop();
return nRet;
}
在CMessageLoop
内循环消息.放入全局
消息映射组.按线程
索引.有过滤消息/处理空闲
,界面元素
可有自己的空闲处理
.将自身
加入消息循环的处理器数组
中即可.Run
包含主消息映射
:
MSG m_msg;
int CMessageLoop::Run()
{
for (;;)
{
while (!::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
DoIdleHandlers();//空闲
bRet = ::GetMessage(&m_msg, NULL, 0, 0);
if(bRet == -1)continue;
else if(!bRet)break;
if (!DoMessageFilters(&m_msg))
{
::TranslateMessage(&m_msg);
::DispatchMessage(&m_msg);
}//分发
}
return (int)m_msg.wParam;
}
多界面线程,则用wtl
的线程管理器
.
int nRet = m_dwCount;
DWORD dwRet;
while(m_dwCount > 0)
{
dwRet = ::MsgWaitForMultipleObjects(m_dwCount, m_arrThreadHandles,
FALSE, INFINITE, QS_ALLINPUT);
if(dwRet >= WAIT_OBJECT_0 && dwRet <= (WAIT_OBJECT_0 + m_dwCount - 1))
RemoveThread(dwRet - WAIT_OBJECT_0);//删线程
else if(dwRet == (WAIT_OBJECT_0 + m_dwCount))
{
::GetMessage(&msg, NULL, 0, 0);
if(msg.message == WM_USER)
AddThread(_T(""), SW_SHOWNORMAL);//加线程,加了就启动
}
}
在移出线程/收到WM_USER消息
时,断开wait
.也可在线管
中加入自己的消息处理器
.当有多种窗口类型
时,要创建窗口,只需要任意窗口执行.
::PostThreadMessage(_Module.m_dwMainThreadID, WM_USER, 0, 0L);
界面线程,有个线程过程
.线管用了MsgWaitForMultipleObjects
,因而最多MAXIMUM_WAIT_OBJECTS(64)
线程,最多63
个窗口.
框架
wtl,两类窗口:框架/视图
窗口.框架提供标题栏/边框
,代码处理工具条/菜单
.视图
为客户区
.
线程创建主框架
,在WM_CREATE
中创建视图
.sdi
中拥有个
视图类,调用创建
就好了.MDI
,则在CMDIFrameWindowImpl<>::CreateMDIClient()
中建立叫MDICLIENT
的窗口.将CMDIChildWindowImpl<>
作为子窗口(有视图),即mdi
具1/多
窗口(有边框/标题栏
等).
LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&)
{
//创建工具栏(命令栏)
HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault,
NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
//加框架菜单(工具栏菜单)
m_CmdBar.AttachMenu(GetMenu());
//加图标
m_CmdBar.LoadImages(IDR_MAINFRAME);
//删旧菜单,
SetMenu(NULL);
HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME,
FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);
CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);//工具条,关联至命令栏
AddSimpleReBarBand(hWndCmdBar);
//钢筋条.是个容器,命令栏,工具栏.
AddSimpleReBarBand(hWndToolBar, NULL, TRUE);
CreateSimpleStatusBar();
m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,WS_EX_CLIENTEDGE);//句柄.
UIAddToolBar(hWndToolBar);//运行时改变
UISetCheck(ID_VIEW_TOOLBAR, 1);
UISetCheck(ID_VIEW_STATUS_BAR, 1);
CMessageLoop* pLoop = _Module.GetMessageLoop();
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);//两个过滤
return 0;
}
class CMainFrame :
public CFrameWindowImpl<CMainFrame>,
public CUpdateUI<CMainFrame>,
public CMessageFilter,
public CIdleHandler
//主框架
CUpdateUI<>
支持更新界面映射
.
视图
class CMyView : public CWindowImpl<CMyView>
{
public:
DECLARE_WND_CLASS(NULL)
BOOL PreTranslateMessage(MSG* pMsg)
{
pMsg;return FALSE;
}
BEGIN_MSG_MAP(CMyView)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
END_MSG_MAP()
LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&)
{
CPaintDC dc(m_hWnd);//待办:加绘画代码
return 0;
}
};
多线程SDI和MDI
差不多,但没有PreTranslateMessage
方法.sdi
利用它,在框架
处理前分发处理
消息,一般是转发消息
给视图类.
要支持鼠标键盘
,则加相应消息处理
函数至消息映射
.如果想基于控件,则加入AtlCtrls.h
.
要加入滚动条:
class CMyView : public CScrollWindowImpl<CMyView>
{
public:
typedef CScrollWindowImpl<CMyView> parent;
BEGIN_MSG_MAP(CMyView)
CHAIN_MSG_MAP(parent)//链上.
END_MSG_MAP()
void DoPaint(CDCHandle dc)//函数换了.
{//画整个视图,不是`WM_PAINT`
}
};
要指定滚动范围,大小或起点
,要在WM_CREATE
中初化.框架窗口
会改变视图窗口
大小.你还可用分割器窗口
,这样,一边树视
,一边列视
.
你要改变框架窗口
,让分割器窗口
作为视图.如框架中有
:
CSplitterWindow m_view;
CTreeViewCtrl m_tree;
CListViewCtrl m_list;
在创建时
:
RECT rect;
GetClientRect(&rect);//取客户区.
m_hWndClient = m_view.Create(m_hWnd, rect,
NULL, WS_CHILD | WS_VISIBLE);//视图创建客户
m_tree.Create(m_view, rcDefault, NULL,WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT,WS_EX_CLIENTEDGE);//树视
m_list.Create(m_view, rcDefault,NULL, WS_CHILD | WS_VISIBLE | LVS_REPORT, WS_EX_CLIENTEDGE);//列视
m_view.SetSplitterPanes(m_tree, m_list);
m_view.SetSplitterPos();//无参时,中线为0,出现在最左边,隐藏了左窗口.
分割器
像视图
一样,以框架
为父窗口
,也可用rcDefault
.在WM_SIZE
时调整.
创建分割器
窗口后,要创建子窗口,用SetSplitterPanes
确定分割条位置.
更新界面
可使能
菜单,可带勾
标记,或单选/多选
.菜单可有图标和文字
.运行时,都可改变.工具栏
只是菜单
的外化.因而可有效分组.更新界面
让你指定哪些界面
运行时可改变.通过更新界面宏
来实现.
BEGIN_UPDATE_UI_MAP(CMainFrame)
UPDATE_ELEMENT(ID_FILE_SAVERESULTS, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
END_UPDATE_UI_MAP()
wtl
建立数组来保存这些信息.
改变状态:
项 |
命令 |
---|---|
菜单,工具条按钮 |
UIEnable |
勾号 |
UISetCheck |
菜单文字 |
UISetText |
选入选出 |
UISetRadio/UISetCheck |
如:
BOOL bSelected = GetSelected();//条件
//是否选中文本.
UIEnable(ID_EDIT_CUT, bSelected);//是否允许
可放入相应处理函数/OnIdle
中,检查类变量
来决定元素状态
.
还要确定,是否都更新了,调用CUpdateUI<>
的某个方法来加入界面元件
至列表,已自动加入主菜单
.
其他通过UIAddMenuBar()和UIAddToolBar()
等来加入菜单/工具栏
.
设置工具栏
状态后,用UIUpdateToolBar
更新状态.而菜单
不必这样,因为是动态
生成子菜单
的.而UIUpdateMenuBar
为恢复初始状态.UISetRadio(多个只单选)
很少用,要自己编码.
对话框
wtl
加了输入验证和回调函数
.如:你想在用户改变打开对话框
中文件夹时动作,从CFileDialogImpl<>
继承,并实现OnFolderChange
函数.
class CMyFileDialog : public CFileDialogImpl<CMyFileDialog>
{
public:
CMyFileDialog(BOOL b)
: CFileDialogImpl<CMyFileDialog>(b) { }
void OnFolderChange(LPOFNOTIFY lpon)
{
char strFolder[MAX_PATH];
if (GetFolderPath(strFolder, sizeof(strFolder)) > 0)//基类的.取路径.
{
MessageBox(strFolder);
}
}
};
这样,改变文件夹
时就执行了.
控件
WTL
为所有的Win32和通用控件
提供了封装类.
两种使用方法:如对话框
中有控件
,将控件
的HWND
依附至封装对象
,用其方法来访问控件
,简化读写控件数据和处理通知消息
.
二,把类加入视图类的继承
中.
class CMyView : public CWindowImpl<CMyView, CListBox>
//该窗口,从CListBox继承,
用GetWndClassName
取得窗口类
名字.消息
会传给你,如未处理由父窗口搞定.
发生事件时,多数窗口控件
会发送通知
给父窗口
.由窗口
来处理.如要处理按钮点击
时,只需处理BN_CLICKED
通知,由按钮
发送给窗口类
.或从CContainedWindow<>
继承按钮窗口来处理点击
事件.处理通知消息
更快,继承麻烦.wtl
还提供了命令栏
.其他有用类:
类 |
描述 |
---|---|
CBitmapButton |
位图 代替标题,可提供列表,在正常状态,失效, 推入和鼠标落在按钮上 等时切换 |
CHyperLink |
超链接 ,点击时,打开网页 . |
CWaitCursor |
构造时等待 ,析构时还原 . |
CCheckListViewCtrl |
检查列表框. |
CMultiPaneStatusBarCtrl |
多面板状态栏. |