RECT
类型定义
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
说明
这是windows广泛采用的一种数据结构,通常作为参数传递给许多api函数。RECT结构表示一个矩形区域,left和top字段描叙了矩形第一个角(通常是左上角),right和bottom字段描叙了矩形的第二个角(通常是右下角)。这两个位置决定了矩形的大小与位置。这些字段采用的单位及坐标系统取决于当前的有效缩放比例、准备表示的对象以及准备调用的api函数。并不要求bottom字段的绝对值大于top字段,而且也可以为负数。
注意
由right及bottom字段指定的点通常不是矩形的一部分;矩形对象描叙的是个空矩形(其中不包含像素);RECT结构要求按引用传递给windows函数,不要试图使用ByVal
GetClientRect - 函数功能
该函数获取窗口客户区的坐标。客户区坐标指定客户区的左上角和右下角。由于客户区坐标是相对子窗口客户区的左上角而言的,因此左上角坐标为(0,0)
函数原型:BOOL GetClientRect(HWND hWnd,LPRECT lpRect);
GetClientRect - 参数
第一个参数是程序窗口的句柄。第二个参数是一个指标,指向一个RECT型态的rectangle结构.该结构有四个LONG字段,分别为left,top,right和bottom.GetClientRect将这四个字段设定为窗口显示区域的尺寸。left和top字段通常设定为0。right和bottom字段设定为显示区域的宽度和高度(像素点数)。
CSize类
类CSize是对Windows结构SIZE的封装,凡是能用SIZE结构的地方都可以用CSize代替。
结构SIZE表示一个矩形的长度和宽度,其定义为:
typedef struct tagSIZE{
LONG cx;
LONG cy;
} SIZE;
其中 cx、cy分别是长度和宽度。
与CPoint类似,CSize也提供了一些重载运算符。如运算符“+”,“-”,“+=”和“-=”,用于两个CSize对象或一个CSize对象与一个CPoint对象的加减运算,运算符“==”和“!=”用于比较两个CSize对象是否相等。
由于CPoint和CSize都包含两个整数类型的成员变量,他们可以进行相互操作。CPoint对象的操作可以以CSize对象为参数。同样,CSize对象的操作也可以以CPoint对象为参数。如可以用一个CPoint对象构造一个CSize对象,也可以用一个CSize对象构造一个CPoint对象,允许一个CPoint对象和一个CSize对象进行加减运算。
CPen
1.CPen类构造函数该类共重载了3个构造函数;
CPen( );
CPen(int nPenStyle, int nWidth, COLORREF crColor);
throw(CResourceException);
CPen(int nPenStyle, int mWidth, const LOGVRUSH* pLogBrush, int nStyleCount=0, const DWORD* lpStyle=NULL);
throw(CResourceException);
参数nPenStyle的值
参数值 注释
PS_SOLID 创建一个实线画笔
PS_DASH 创建一个虚线画笔,该值只有当画笔宽度等于1个设备单位或更小时才有效
PS_DOT 创建一个点线画笔,该值只有当画笔宽度等于1个设备单位或更小时才有效
PS_DASHDOT 创建一个点和虚线交替画笔,该值只有当画笔宽度等于1个设备单位或更小时才有效
PS_DASHDOTDOT 创建一个双点线画笔,该值只有当画笔宽度等于1个设备单位或更小时才有效
PS_NULL 创建一个空线画笔
PS_INSIDEFRAME 创建一个内框线画笔,该画笔可以在WindowsGDI输出函数定义的矩形边界所生成的封闭形状的边框内绘制直线
PS_GEOMETRIC 创建一个几何画笔
PS_COSMETIC 创建一个装饰画笔
PS_ALTERNATE 创建一个设置其他像素的画笔
PS_USERSTYLE 创建一个使用由用户提供的风格矩阵的画笔
PS_ENDCAP_ROUND 尾帽为圆形的
PS_ENDCAP_SQUARE 尾帽为方形的
PS_ENDCAP—FLAT 尾帽为平坦的
PS_JOIN_BEVEL 成尖角连接
PS_JOIN_MITET 通过setMiterLimit函数设置的当前极限值范围内斜接;否则,成尖角连接
PS_JOIN_ROUND 成圆角连接
参数pLogBrush指向一个LOGBRUSH结构。该结构原型声明如下:
typedef struct tag LOGBRUSH{ /*lb*/
UINT lbStyle;
COLORREF lbColor;
LONG lbHatch;
}LOGBRUSH;
该结构定义了一个画刷的风格、颜色和阴影线种类。
画刷的风格值
参数值 说明
BS_DIBPATTERN 由设备无关的位图定义的图形画刷。如果该参数值为该值,则成员lbHatch包含了一个被压缩的DIB句柄
BS_DIBPATTERNPT 由设备无关的位图定义的图形画刷。如果该参数值为该值,则成员lbHatch包含了一个被压缩的DIB指针
BS_HATCHED 阴影线画刷
BS_HOLLOW 中空画刷
BS_NULL 与参数值为BS_HOLLOW定义相同的画刷
BS_PATTERN 由内存位图定义的图形画刷
BS_SOLID 实画刷
BS_NULL 与参数值为BS_HOLLOW定义相同的画刷
BS_PATTERN 由内存位图定义的图形画刷
BS_SOLID 实画刷
2、CPen类初始化成员函数
(1)CreatePen( )成员函数其原型声明如下:
BOOL CreatePen(int nPenStyle,int nWidth,const LOGBRUSH* pLogBrush,int nStyleCount=0,const DWORD*lpStyle=NULL);
(2)CreatePenIndirect( )成员函数的原型声明如下:
BOOL CreatePenIndirect(LPLOGPEN lpLogPen);
LOGPEN结构的具体定义如下:
typedef struct tagLOGPEN{ // lgpn
UNIT lopnStyle;
POINT lopnWidth;
COLORREF lopnColor;
}LOGPEN;
可以使用RGB宏来完成颜色设定:
COLORREF RGB(cRed,cGreen,cBlue);
也可以使用COLORREF,其结构为0x00bbggrr。
注:COLORREF实际上就是一个DWORD类型的。所有如果进行颜色传递直接按%d格式就可以,不需要格式的转换。
CString
CString 是一种很有用的数据类型。它们很大程度上简化了MFC中的许多操作,使得MFC在做字符串操作的时候方便了很多。不管怎样,使用CString有很多特殊的技巧,特别是对于纯C背景下走出来的程序员来说有点难以学习。这篇文章就来讨论这些技巧。
使用CString可以让你对字符串的操作更加直截了当。这篇文章不是CString的完全手册,但囊括了大部分常见基本问题。
这篇文章包括以下内容:
CString 对象的连接
格式化字符串(包括 int 型转化为 CString )
CString 型转化成 int 型
CString 型和 char* 类型的相互转化
char* 转化成 CString
CString 转化成 char* 之一:使用LPCTSTR强制转化
CString 转化成 char* 之二:使用CString对象的GetBuffer方法
CString 转化成 char* 之三: 和控件的接口
CString 型转化成 BSTR 型;
BSTR 型转化成 CString 型;
VARIANT 型转化成 CString 型;
载入字符串表资源;
CString 和临时对象;
CString 的效率;
总结
下面我分别讨论。
[编辑本段]1、CString 对象的连接
能体现出 CString 类型方便性特点的一个方面就字符串的连接,使用 CString 类型,你能很方便地连接两个字符串,正如下面的例子:
CString gray("Gray");
CString cat("Cat");
CString graycat = gray + cat;
要比用下面的方法好得多:
char gray[] = "Gray";
char cat[] = "Cat";
char * graycat = malloc(strlen(gray) + strlen(cat) + 1);
strcpy(graycat, gray);
strcat(graycat, cat);
[编辑本段]2、格式化字符串
与其用 sprintf() 函数或 wsprintf() 函数来格式化一个字符串,还不如用 CString 对象的Format()方法:
CString s;
s.Format(_T("The total is %d"), total);
用这种方法的好处是你不用担心用来存放格式化后数据的缓冲区是否足够大,这些工作由CString类替你完成。
格式化是一种把其它不是字符串类型的数据转化为CString类型的最常用技巧,比如,把一个整数转化成CString类型,可用如下方法:
CString s;
s.Format(_T("%d"), total);
我总是对我的字符串使用_T()宏,这是为了让我的代码至少有Unicode的意识,当然,关于Unicode的话题不在这篇文章的讨论范围。_T()宏在8位字符环境下是如下定义的:
#define _T(x) x // 非Unicode版本(non-Unicode version)
而在Unicode环境下是如下定义的:
#define _T(x) L##x // Unicode版本(Unicode version)
所以在Unicode环境下,它的效果就相当于:
s.Format(L"%d", total);
如果你认为你的程序可能在Unicode的环境下运行,那么开始在意用 Unicode 编码。比如说,不要用 sizeof() 操作符来获得字符串的长度,因为在Unicode环境下就会有2倍的误差。我们可以用一些方法来隐藏Unicode的一些细节,比如在我需要获得字符长度的时候,我会用一个叫做DIM的宏,这个宏是在我的dim.h文件中定义的,我会在我写的所有程序中都包含这个文件:
#define DIM(x) ( sizeof((x)) / sizeof((x)[0]) )
这个宏不仅可以用来解决Unicode的字符串长度的问题,也可以用在编译时定义的表格上,它可以获得表格的项数,如下:
class Whatever { ... };
Whatever data[] = {
{ ... },
...
{ ... },
};
for(int i = 0; i < DIM(data); i++) // 扫描表格寻找匹配项。
这里要提醒你的就是一定要注意那些在参数中需要真实字节数的API函数调用,如果你传递字符个数给它,它将不能正常工作。如下:TCHAR data[20];
lstrcpyn(data, longstring, sizeof(data) - 1); // WRONG!
lstrcpyn(data, longstring, DIM(data) - 1); // RIGHT
WriteFile(f, data, DIM(data), &bytesWritten, NULL); // WRONG!
WriteFile(f, data, sizeof(data), &bytesWritten, NULL); // RIGHT
造成以上原因是因为lstrcpyn需要一个字符个数作为参数,但是WriteFile却需要字节数作为参数。
同样需要注意的是有时候需要写出数据的所有内容。如果你仅仅只想写出数据的真实长度,你可能会认为你应该这样做:
WriteFile(f, data, lstrlen(data), &bytesWritten, NULL); // WRONG
但是在Unicode环境下,它不会正常工作。正确的做法应该是这样:
WriteFile(f, data, lstrlen(data) * sizeof(TCHAR), &bytesWritten, NULL); // RIGHT
因为WriteFile需要的是一个以字节为单位的长度。(可能有些人会想"在非Unicode的