1.#pragma comment 的使用方法
#pragma comment ( lib,"wpcap.lib" )
表示链接wpcap.lib这个库。
和在工程设置里写上链入wpcap.lib的效果一样(两种方式等价,或说一个隐式一个显式调用),不过这种方法写的 程序别人在使用你的代码的时候就不用再设置工程settings了。告诉连接器连接的时候要找ws2_32.lib,这样你就不用在linker的lib设置里指定这个lib了。
比如:
#include "Mwic_32.h"
#pragma comment(lib,"Mwic_32.lib")
就不需要在project setting里面设置了
注释 pragma 可以允许用户在目标文件或可执行文件中插入注释。lib 指定符允许用户向链接器传递该注释,以在使用对象模块时指定其它的链接库。有些用户使用 lib 注释 pragma 以添加链接器选项和库名,例如:
#pragma comment(lib, "MSVCRT -VERBOSE")
在 Visual C++ 2.x 中,代码行照原样将字符串传递给链接器,结果导致编译时附加了 /VERBOSE 链接器选项和 MSVCRT.LIB 库。但是,这种情况并不仅限于上述方式。编译器不会将注释字符串放在引号内,而会用空格分隔文本。
在 Visual C++ 4.0、4.1、和 4.2 中,编译器将注释字符串正确地放在引号内,因而导致上述代码产生以下错误:
LINK :fatal error LNK1104:cannot open file "MSVCRT -VERBOSE.lib"
// Compile options needed:none
// test.c
#pragma comment(lib,"MYLIBRARY -VERBOSE")
void main(void)
{
}
#pragma comment( comment-type [,"commentstring"] )
参考链接:https://blog.csdn.net/haiross/article/details/44940455
2.基本类
一、核心类
1. CWindowWnd,窗口对象管理父类,主要作用:
1) 创建窗口。
2) 窗口消息过程处理。
3) 提供窗口子类化与超类化接口。
2. CDialogBuilder,控件布局类,主要作用:
1) 读取XML脚本,分析脚本,构建控件树。
2) 创建控件对象。
3. CPaintManagerUI,窗口消息及图形绘制管理器类,与窗口绑定,主要作用:
1) 绘制控件。
2) 消息管理。
3) 事件通知。
4. INotifyUI,事件通知抽象类,主要作用:
1) 重载Notify虚函数,处理事件通知。
二、控件类
1. CControlUI,控件管理父类,主要作用:
1) 控件的通用基类,提供控件通用属性管理。
2. CLabelUI,静态标签类,父类CControlUI。
3. CButtonUI,按钮类,父类CLabelUI。
4. COptionUI,选择按钮类,父类CButtonUI。
5. CTextUI,静态文本类,父类CLabelUI。
6. CProgressUI,进度条类,父类CLabelUI。
7. CSliderUI,父类CProgressUI。
8. CEditUI,编辑框类,父类CLabelUI。
9. CListUI,列表框类,父类CVerticalLayoutUI、IListUI。
1) CListHeaderUI,父类CHorizontalLayoutUI。
2) CListHeaderItemUI,列表头类,父类CControlUI。
3) CListTextElementUI,类表文本类,父类CListLabelElementUI。
4) CListLabelElementUI,父类CListElementUI。
10. CComboUI,组合框类,父类CContainerUI、IListOwnerUI。
11. CActiveXUI,ActiveX控件类,父类CControlUI、 IMessageFilterUI。
12. CContainerUI,容器类,父类CControlUI、IContainerUI。
13. CTabLayoutUI,选项页布局类,父类CContainerUI。
14. CTileLayoutUI,父类CContainerUI。
15. CDialogLayoutUI,对话框布局类,父类CContainerUI。、
16. CVerticalLayoutUI,垂直布局类,父类CContainerUI。
17. CHorizontalLayoutUI,水平布局类,父类CContainerUI。
18. CListExpandElementUI,父类CListTextElementUI。
19. CListContainerElementUI,父类CContainerUI、IListItemUI。
三、辅助类
1. CStdPtrArray,指针数组。
2. CStdValArray,数据数组。
3. CStdString,字符串数组。
4. CStdStringPtrMap,字符串指针映射数组。
参考链接:https://www.cnblogs.com/xubin0523/archive/2012/06/01/2530901.html
3.CDuiString类
它是Duilib库中对字符串对象的一个封装,里面包含了对字符串的常用操作。
4.GetSkinFolder ()与 SetResourcePath()
(1)关于资源设置的函数说明:
这三个函数的说明如下:
1、 GetSkinFolder () 需要返回 皮肤XML 所在的文件夹
2、GetSkinFile () 需要返回 皮肤 XML 的文件名(也可以包含路径)
3、GetWindowClassName () 需要返回这个窗口的类名,这个类名用于 RegisterClass.
这三个函数告知duilib库应该从哪个文件夹下解析哪个xml文件,并定义对应窗口的名字,以后这个类就代表这个xml文件所描述的窗口
需要注意的是这些函数必须在头文件中这样写,我自己写在CPP文件中它在运行时报错,可能是库本身的bug
(2)注意事项:
实际如果 SetResourcePath 设定了目录, GetSkinFolder 无效,只能通过 GetSkinFile 来实现,可以以这种方式返回 _T("about/about.xml");,实际上就是 GetSkinFile 做了 GetSkinFolder + GetSkinFile 的工作
WindowImplBase已经将CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath())封装到内部了,GetSkinFolder 在此路径基础上设定资源文件夹路径
CPaintManagerUI::GetInstancePath()的路径是生成exe的路径
参考链接:duilib基本流程
5.C++ - _T含义 C++语言中“_T”是什么意思?
_T("")是一个宏,定义于tchar.h下。
#define __T(x) L ## x
#define _T(x) __T(x)
--------------------------------------------------------------
_T("Hello")是一个宏,他的作用是让你的程序支持Unicode编码,因为Windows使用两种字符集ANSI和UNICODE,前者就是通常使用的单字节方式,但这种方式处理象中文这样的双字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。
Windows NT的所有与字符有关的函数都提供两种方式的版本,而Windows 9x只支持ANSI方式。
如果你编译一个程序为ANSI方式,_T实际不起任何作用。而如果编译一个程序为UNICODE方式,则编译器会把"Hello"字符串以UNICODE方式保存。
_T和_L的区别在于,_L不管你是以什么方式编译,一律以UNICODE方式保存。
---------------------------------------------------------------------------------------------------------------
1\C++语言中“_T”是什么意思?
Visual C++里边定义字符串的时候,用_T来保证兼容性,VC支持ascii和unicode两种字符类型,用_T可以保证从ascii编码类型转换到unicode编码类型的时候,程序不需要修改。
如果将来你不打算升级到unicode,那么也不需要_T,
---------------------------------------------------------
_t("hello world")
在ansi的环境下,它是ansi的,如果在unicode下,那么它将自动解释为双字节字符串,既unicode编码。
这样做的好处,不管是ansi环境,还是unicode环境,都适用。
2\请问在vc++中的字符串_T("ABC")和一个普通的字符串“ABC”有什么区别。
_T("ABC")
表示如果定义了unicode
它表示 L"ABC",每个字符为16位,宽字符字符串
---------------------------------------------------------
if not UNICODE
它就是ascii的"ABC",每个字符为8位
"ABC"就是指ascii字符串"ABC"
----------------------------------------------------------
相当于
#ifdef _UNICODE
#define _T("ABC") L"ABC"
#else
#define _T("ABC") "ABC"
#endif
----------------------------------------------------------
_T("ABC")中的一个字符和汉字一样,占两个字节,而在"ABC"中,英文字符占一个字节,汉字占两个字节
---------------------------------------------------------------------------------------------------------------
_T在tchar.h头文件中定义了:
#define __T(x) L ## x
#define _T(x) __T(x)
-- ##在宏里面相当于连接符,把前后两个字符串连在一起作为一个字符串。
以下来自网络:
#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x
x##y表示什么?表示x连接y,举例说:
int n = Conn(123,456); 结果就是n=123456;
char* str = Conn("asdf", "adf")结果就是 str = "asdfadf";
怎么样,很神奇吧
再来看#@x,其实就是给x加上单引号,结果返回是一个const char。举例说:
char a = ToChar(1);结果就是a='1';
做个越界试验char a = ToChar(123);结果是a='3';
但是如果你的参数超过四个字符,编译器就给给你报错了!error C2015: too many characters in constant :P
最后看看#x,估计你也明白了,他是给x加双引号
char* str = ToString(123132);就成了str="123132";
参考链接:https://blog.csdn.net/CNHK1225/article/details/45097281
7.关于Notify:
(1)消息泵的处理流程
WindowImplBase的OnCreate函数默认会将自身添加成CPaintManagerUI Notify消息的Notifier,WindowImplBase对象相当于是事件消息的一个监听者,当有事件发生时,会调用WindowImplBase的Notify函数,而Notify函数会调用CNotifyPump::NotifyPump进入消息泵。进入消息泵后,先查看当前窗口类中有无虚拟窗口对事件进行处理,如果没有,就查找当前窗口类是否有函数对其进行处理,如果没有,进入父类进行类似查找,直到CNotifyPump类。
(2)控件响应处理:
父类 WindowImplBase 提供了 Notify 虚函数,可以提供我们覆写并处理消息。最后别忘记调用父类的 Notify 函数来继续其他消息的处理(其实父类什么都没做,)。
void MyMainWindow::Notify(TNotifyUI& msg)
{
if (msg.sType == _T("click"))
{
CDuiString sName = msg.pSender->GetName();
if (sName == _T("closebtn"))
{
Close(IDOK);
PostQuitMessage(0);
return;
}
}
WindowImplBase::Notify(msg);
}
参考链接:控件消息响应处理
(3)消息队列机制:(扩展)
参考链接:https://blog.csdn.net/xiaojun111111/article/details/49565719
8.duilib关闭窗口方式:
Close(IDOK) , Close(IDCANCEL);
9.void PostQuitMessage(0)函数:
//void PostQuitMessage(int nExitCode)函数的作用是向程序发送WM_QUIT消息,nExitCode应用程序退出代码
PostQuitMessage(0); //调用该函数发出WM_QUIT消息
(1)WM消息传递过程原理:
从用户单击关闭按钮(标题栏最右边)或者用鼠标或鍵盘选择系统菜单的“关闭”选项,直到窗口消失,应用程序结束。这期间到底发生了什么呢?这曾经是我百思不得其解的问题,我想也会有很多人和我一样会碰到这个问题。所以我要把我的一些学习心得写出来,与大家共享:
1、首先会产生一个WM_SYSCOMMAND消息,如果程序员没有对此消息进行拦截,则由缺省的窗口函数DefWindowProc进行处理,如果表达式(LOWORD(wParam)&0xFFF0)==SC_CLOSE 成立,DefWindowProc发出一个WM_CLOSE消息。
2、同样,如果程序员没有对WM_CLOSE消息进行拦截,则还是由DefWindowProc进行处理,这次,她只简单的调用 DestroyWindow函数,DestroyWindow先把窗口破坏掉,使用户看不到窗口。但是窗口破坏后,应用程序并没有结束,于是 DestroyWindow再接再励,送出了一个WM_DESTROY消息。
3、这一次,WM_DESTROY被载获了,通常是会有这样的句子:
case WM_DESTROY:
PostQuitMessage(0);
...
这里PostQuitMessage函数很简单的发送一个WM_QUIT消息来响应WM_DESTROY
4、WM_QUIT消息非常特殊,她使GetMessage函数返回0,从而结束了消息循环,
应用程序从此结束。
(2)扩展:WM_CLOSE WM_QUIT WM_DESTROY 三者的区别
一直以来,我都不是很明白这三个的区别,今天看了一写文章,才明白过来,一下是转载的文字:
有三个消息看 起来差不多,都是处理关闭的事情的。它们是WM_DESTROY,WM_CLOSE,和WM_QUIT。它们的确很相似,但你需要知道它们之间的不同!一 个窗口或者应用程序应该被关闭时发出WM_CLOSE消息,当接收到WM_CLOSE消息时,如果你愿意,向用户提出是否真的退出。你知道让用户作确认或 有错误出现或有什么应该注意的事情发生的时候,往往弹出一个消息框。
插播消息框
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
当收到WM_CLOSE消息,你可以做两件事儿。一件是你接受默认的处理返回一个值,你若这样做了,应用程序或窗口按照计划关闭;再者,你返回0,应用程序或窗口将保持原样。以下是代码的基本部分:
if (msg == WM_CLOSE)
{
if (MessageBox(hMainWindow, "Are you sure want to quit?", "Notice", MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
return(0);
// otherwise, let the default handler take care of it
}
WM_DESTROY消息有点儿不同。它是窗口正在关闭时发出的。
当得到WM_DESTROY消息的时候,窗口已经从视觉上被删除。
一个主窗口被关闭,并不意味着应用程序结束了,它将在没有窗口的条件下继续运行。
然而,当一个用户关闭了主窗口,也就意味着他要结束应用程序,所以如果你希望应用程序结束,在收到WM_DESTROY消息的时候,你必须发出一个WM_QUIT消息。
WM_QUIT是应用程序结束发出的消息,一般可以看成进程被kill掉的情况.
PostQuitMessage是向系统发出要终止线程的请求, 在终止线程前系统还要做些内存的清理工作, 我们关闭一个程序时是发送WM_CLOSE消息, 然后调用DestroyWindow函数,调用DestroyWindow时系统会向程序发WM_DESTROY消息,终止整个程序
用自己的话总结一下:WM_CLOSE 消息发出的时候,用户可以根据自己的意愿来选择到底是否关闭,WM_DESTORY 是真的关闭一个窗口。WM_QUIT是退出一个应用程序
参考链接:https://blog.csdn.net/tunnel115/article/details/4546913