技术标签: 笔记
应用程序类型 |
描述 |
---|---|
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 |
多面板状态栏. |
文章浏览阅读4.4k次。1.7-savingPNG介绍代码详情函数详解savePNGFile()源码savePNGFile()源码提示savePNGFile()推荐用法处理结果代码链接介绍PCL提供了将点云的值保存到PNG图像文件的可能性。这只能用有有序的云来完成,因为结果图像的行和列将与云中的行和列完全对应。例如,如果您从类似Kinect或Xtion的传感器中获取了点云,则可以使用它来检索与该云匹配的640x480 RGB图像。代码详情#include <pcl / io / pcd_io.h>#incl_pcl::io:savepng
文章浏览阅读936次。吸引妹子的关键点不在于喝什么咖啡,主要在于竖立哪种男性人设。能把人设在几分钟内快速固定下来,也就不愁吸引对口的妹子了。我有几个备选方案,仅供参考。1. 运动型男生左手单手俯卧撑,右手在键盘上敲代码。你雄壮的腰腹肌肉群活灵活现,简直就是移动的春药。2.幽默男生花 20 块找一个托(最好是老同学 or 同事)坐你对面。每当你侃侃而谈,他便满面涨红、放声大笑、不能自已。他笑的越弱_咖啡厅写代码
文章浏览阅读1.2w次,点赞5次,收藏5次。今天 (应该是昨天了,昨晚太晚了没发出去)下午参加了腾讯WXG的面委会面试。前面在牛客上搜索了面委会相关的面经普遍反映面委会较难,因为都是微信的核心大佬,问的问题也会比较深。昨晚还蛮紧张的,晚上都没睡好。面试使用的是腾讯会议,时间到了面试官准时进入会议。照例是简单的自我介绍,然后是几个常见的基础问题:例如数据库索引,什么时候索引会失效、设计模式等。这部分比较普通,问的也不是很多,不再赘述。现在回想下,大部分还是简历上写的技能点。接下来面试官让打开项目的代码,对着代码讲解思路。我笔记本上没有这部分代码,所_腾讯面委会面试是什么
文章浏览阅读382次,点赞3次,收藏4次。AI绘画自动生成器是一种利用人工智能技术,特别是深度学习算法,来自动创建视觉艺术作品的软件工具。这些工具通常基于神经网络模型,如生成对抗网络(GANs),通过学习大量的图像数据来生成新的图像。AI绘画自动生成器作为艺术与科技结合的产物,正在开启艺术创作的新篇章。它们不仅为艺术家和设计师提供了新的工具,也为普通用户提供了探索艺术的机会。随着技术的不断进步,我们可以预见,AI绘画自动生成器将在未来的创意产业中发挥越来越重要的作用。
文章浏览阅读1.6w次,点赞3次,收藏13次。老规矩,二话不说直接上代码:package com.poinne17.test;import org.apache.commons.collections.CollectionUtils;import org.junit.Test;import java.util.*;/** * @author:Pionner17 * @date: 2017/9/3 22:41 * @em_list找到重复的元素
文章浏览阅读1k次。一、zip和unzip 一般情况下,windows中的压缩包都是rar或者zip格式,对应的压缩软件为winzip和winrar。winzip是免费的,winrar是收费的。rar比zip压缩率更高,即同样的文件压缩完后体积更小,同时因为国内盗版,以及winrar安装后,右击默认压缩为rar的原因,导致国内的rar的使用率远超zip。 放眼全世界,zip的使用率反而远超rar,在ubuntu中,zip是默认安装的,免费使用,而rar需要额外安装,并且收费。故在linux中一般情况下,我们使用zip格_winzip收费
文章浏览阅读1.7k次。理解为ListView 的三种形式吧ListView 默认构造但是这种方式创建的列表存在一个问题:对于那些长列表或者需要较昂贵渲染开销的子组件,即使还没有出现在屏幕中但仍然会被ListView所创建,这将是一项较大的开销,使用不当可能引起性能问题甚至卡顿直接返回的是每一行的Widget,相当于ios的row。行高按Widget(cell)高设置ListView.build 就和io..._flutter listview.separated和listview.builder
文章浏览阅读1.4k次,点赞4次,收藏14次。废话不多说直接上干货1.js运行机制JavaScript单线程,任务需要排队执行同步任务进入主线程排队,异步任务进入事件队列排队等待被推入主线程执行定时器的延迟时间为0并不是立刻执行,只是代表相比于其他定时器更早的被执行以宏任务和微任务进一步理解js执行机制整段代码作为宏任务开始执行,执行过程中宏任务和微任务进入相应的队列中整段代码执行结束,看微任务队列中是否有任务等待执行,如果有则执行所有的微任务,直到微任务队列中的任务执行完毕,如果没有则继续执行新的宏任务执行新的宏任务,凡是在..._前端面试
文章浏览阅读1k次。(3)若没有查到,则将请求发给根域DNS服务器,并依序从根域查找顶级域,由顶级查找二级域,二级域查找三级,直至找到要解析的地址或名字,即向客户机所在网络的DNS服务器发出应答信息,DNS服务器收到应答后现在缓存中存储,然后,将解析结果发给客户机。(3)若没有查到,则将请求发给根域DNS服务器,并依序从根域查找顶级域,由顶级查找二级域,二级域查找三级,直至找到要解析的地址或名字,即向客户机所在网络的DNS服务器发出应答信息,DNS服务器收到应答后现在缓存中存储,然后,将解析结果发给客户机。_linux
文章浏览阅读7.9k次,点赞26次,收藏66次。HTML DOM——文档元素的操作1、通过id获取文档元素任务描述相关知识什么是DOM文档元素节点树通过id获取文档元素代码文件2、通过类名获取文档元素任务描述相关知识通过类名获取文档元素代码文件3、通过标签名获取文档元素任务描述相关知识通过标签名获取文档元素获取标签内部的子元素代码文件4、html5中获取元素的方法一任务描述相关知识css选择器querySelector的用法代码文件5、html5中获取元素的方法二任务描述相关知识querySelectorAll的用法代码文件6、节点树上的操作任务描述相关_javascript学习手册十三:html dom——文档元素的操作(一)
文章浏览阅读132次。《LeetCode学习》172. 阶乘后的零(java篇)_java 给定一个整数n,返回n!结果尾数中零的数量
文章浏览阅读426次。请注意,本文将要给大家分享的并不是开启公众号的安全操作风险提醒,而是当公众号粉丝给公众号发消息的时候,公众号的管理员和运营者如何能在手机上立即收到消息通知,以及在手机上回复粉丝消息。第一步:授权1、在微信中点击右上角+,然后选择“添加朋友”,然后选择“公众号”,然后输入“微小助”并关注该公众号。2、进入微小助公众号,然后点击底部菜单【新增授权】,如下图所示:3、然后会打开一个温馨提示页面。请一定要..._php微信公众号服务提示