这次记录的关于显示的部分的笔记如与标准(本人学的是Win程序设计第五版)有偏差,或哪里有不妥,欢迎大家给予斧正!
谈到显示,不得不说说ANSI和Unicode
ANSI是一个标准,这个标准说实话每个国家的字符所占大小都是不一的,有的是一个字,有的是一个字节,比如,中文的GBK标准就是占了一个字的,但是这个标准的不变之处是0x0~0x7F这127个字符,后面的则由不同地域的要求来定,如果是这样子的话就会造成每个地方的每个编码标标准都有差异,一个系统要同时兼顾这么多的标准虽然有可行的管理方法,但是还是会出先不兼容的情况,所以就出现了Unicode,Unicode有两个标准和3个编码方案,两个标准是UCS-2和UCS-4
UCS-4的Unicode大小大概在0到|0x7F|FF|FF|FF|
其中7F个组,FF个面,FF行每行有FF个码位
但是由于Unicode计划只是用第0组,前17个面,所以现在的Unicode是从0到0X10FFFF的
只用0面的范围时(即BMP)就只是0到FFFF了,此时就变成了两字节的UCS-2
3个方分别是UTF-8,UTF-16-UTF-32这三种编码方式可以在百度百科里面看到,大概如下:
Unicode编码(十六进制) UTF-8 字节流(二进制)
000000-00007F || 0xxxxxxx
000080-0007FF || 110xxxxx 10xxxxxx
000800-00FFFF || 1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF || 11110xxx10xxxxxx10xxxxxx10xxxxxx
UTF-16:
这个只有两个,分别是:
000000-010000->此时只有0~FFFF用一个字就好
当范围是010000~10FFFF时,就先将编码值减去010000剩下的范围就是0~FFFFF即20位,此时用两个字来保留,分别是:
110110xxxxxxxxxx 110111yyyyyyyyyy
这两个所属值的范围又有:
1101100000000000 ~ 1101101101111111 (D800-DB7F)高位
1101101110000000~ 1101101111111111 (DB80-DBFF)高位
1101110000000000 ~ 1101111111111111 (DC00-DFFF)低位
其中中间的,DB80到DBFF区域是专用区,转换一下:(高后10位结合低后10位)
从1110000000 0000000000到1111111111 1111111111(即E0000到FFFFF)此时再加上0x10000就发现专用区是占用了第0x0F0000到0x10FFFF即第15到16面
UTF-32:
这个就很清真,直接表示了4字节的,不用分,唯一会出不同的地方(包括上面UTF-16以及一个以上字节表示的UTF-8)就是大小端序的差别:
这里的大小端序和高低地址高低位字节解释:
如:
一个内存段1000,偏移量0~FFFF地址高低由偏移量的增加而增高
一个数据0x12345678位是由高到低下降的,所以高位->低位是:12,34,56,78
所以小端序内存排布为:
78,56,34,12
大端序排布相反:
12,34,56,78
那么什么时候用
为了保证代码的一定的兼容性,所以一般使用tchar.h
其中使用的比较频繁的就是:
#ifdef UNICODE
#define WCHAR TCHAR,*PTCHAR;
#define TEXT(x) L##x
#else
#define char TCHAR,*PTCHAR;
#define TEXT(x) x
#endif
#define TEXT(x) __TEXT(x)
那么现在言归正传开始记录Win32程序设计
在绘图中(虽然我是方向主要是启动开发,对GDI的了解要求不高,但是要是有一些要了解到),必须使用DC所以我们要在显示设备上显示东西那么就要用到这个设备描述表的句柄
获取HDC的方式有两种:
1:
hdc = GetDC(hWnd);
对hdc的使用
ReleaseDC(hWnd,hdc);
同时有一个很相似的:
GetWindowDC
这个函数获取的HDC和GetDC的区别在于,后者是获取窗口客户区的HDC而前者是获取整个窗口的HDC这就使得前者在处理客户区的WM_PAINT之外还要处理类似于标题栏的WM_NCPAINT同时这也就可以直接在标题栏上写入文字。
GetDC和ReleaseDC是成对出现的,前者获取HDC而后者主要负责释放,因为有规定:非CreateDC创建的之外,都应该在一个消息期间内获取并释放,不能再两个消息之间保存其他设备句柄。
2:
hdc = BeginPaint(hWnd,&ps)
对hdc的使用
EndPaint(hWnd,&ps)
现在对以上两组函数做一些补充:
1: ps
ps是PAINTSTRUCT类型的,这个类型我们使用的一般只有前三个域
其中第一个域是HDC
第二个域作为BOOL标志是否擦除了客户区中的无效区域(通常为FLASE表示以擦除)
第三个是RECT类型,这个类型中的数据可以准确定义一个矩形,这个矩形通常作为某一块无效区域的外切矩形
2:两者的差别
GetDC是仅仅只是获取HDC但是BeginPaint在获取HDC的同时还会使客户区从无效变为
API介绍:
TextOut这个使基于HDC的一个显示文本的API
函数形式:TextOut(hdc,x,y,psText,iLenth)
书中有一个例子我觉得是非常棒的:
TextOut (hdc, 22 * cxCaps + 40 * cxChar, cyChar * i, szBuffer,
wsprintf (szBuffer, TEXT ("%5d"),
GetSystemMetrics (sysmetrics[i].iIndex))) ;
发现,第二第三个参数分别是插入的文本的x和y(客户区像素)第四个是字符串第五个是长度
没错,这里的长度和字符串赋值是一起的(暂时可以这么看)
因为TextOut函数的点用管理是_stdcall即参数是从右向左入栈,所以一开始是执行了wsprintf的,由于printf的返回值是字符串的长度,所以获取字符串长度和输入szBuffre一气呵成!
ValidateRect
这个函数可以使客户区有效
InvalidateRect
这个函数会迫使客户区内的矩形无效并且根据最后一个参数BOOL类型,来通知是否是用刷子将背景刷新(TRUE刷新,FALSE则保留,保留之前显示的东西,当然,TextOut也可以使要显示的矩形(由X,Y,长度确定的)强行刷新)
消息介绍:
WM_PAINT
这个消息是UpdataWindow函数直接发送消息到窗口过程的,或者是当Windows发现窗口客户区存在无效区域时会自动向消息队列内插入一个此消息,如果消息队列内已有这个消息并且没有被执行那么就不插入。
这时设计WM_PAINT消息的内容就显得有一点点重要了,因为这个消息时被调用的比较频繁地。
那么,结合之前说的API:GetDC和BeginPaint我们知道如果我们要再此用GetDC那么就应该多加一个ValidateRect函数使客户区有效,否则,如果子消息内不存在让客户区有效的语句,Windows则会一直插入这个消息。