第九十一个CreateFont创建一种字体,函数返回字体句柄HFONT
HFONT CreateFont(
int nHeight,//字符高度
int nWidth,//字符宽度,nHeight 和nWidth参数指明字体大小
int nEscapement,//文本显示时的倾斜角度,以字符框左上角为原点,负数表示顺时针旋转,正数逆时针(如2700,旋转270度)
int nOrientation,//字符显示时的倾斜角度。nEscaperment和nOnentation这两个参数一般取0就可以了。
int fnWeight,//字体重量,即字体粗细程序,范围在0到1000之间。填FW_NORMAL就行了
DWORD fdwItalic,//指明字体是否倾斜,true表明是斜体字,false则不是
DWORD fdwUnderline,//指明字体是否具有下划线,true有,false没有。
DWORD fdwStrikeOut,//指明字体是否显示删除线,取值同上。
DWORD fdwCharSet,//指明字符集,填DEFAULT_CHARSET(默认)
DWORD fdwOutputPrecision, //指定输出精度,填OUT_DEFAULT_PRECIS(默认)
DWORD fdwClipPrecision,//指定裁剪精度,填CLIP_DEFAULT_PRECIS(默认)
DWORD fdwQuality,//字符输出质量,填DEFAULT_QUALITY(默认)
DWORD fdwPitchAndFamily,//字符间距,填DEFAULT_PITCH(默认)
LPCTSTR lpszFace//字体名称,如"宋体","黑体".
);
标准创建字体的语句:
HFONT Font=CreateFont(20,20,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,
"宋体");
后面的函数将会有例子
第九十二个BeginPath开启一个路径
需设备DC作参数,开启一个路径后,再调用画图函数在开启路径的DC上的进行操作,则没有实质图形,仅仅是路径,这些路径是看不见,但它确实存在。但可以调用其它函数对路径进行操作,如StroekPath函数,用当前画笔描绘路径。这里还要说明一点,并不是所有的画图函数支持路径的。下面给出支持路径的画图函数:
AngleArc
Arc画弧函数
ArcTo
Chord
CloseFigure
Ellipse画椭圆
ExtTextOut输出文本
LineTo 画直线,与MoveToEx函数结合使用
MoveToEx 画直线
Pie画饼图函数
PolyBezier
PolyBezierTo
PolyDraw
Polygon
Polyline
PolylineTo
PolyPolygon
PolyPolyline
Rectangle画矩形
RoundRect圆色矩形
TextOut输出文本
当不需要再用上面这些函数绘制路径后,就用EndPath函数结束路径
第九十三个StrokePath用当前笔描绘路径
函数只有一个参数,DC句柄。
例子:在一个窗口显示镂空字
#include<windows.h>
int main()
{
HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
HDC dc=GetDC(wnd);
HFONT Font=CreateFont(50,50,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,
"宋体");//创建字体
HPEN pen=CreatePen(PS_SOLID,1,RGB(255,0,0));//创建红色画笔
SelectObject(dc,pen);//选入画笔
SelectObject(dc,Font);//选入字体
SetBkMode(dc,TRANSPARENT);//设置文本背景颜色为透明
while(1)
{
BeginPath(dc);//开启路径
TextOut(dc,0,0,"ABC",3);
EndPath(dc);//结束路径
StrokePath(dc);//用当前画笔描绘路径
Sleep(300);
}
return 0;
}
第九十四个SetWindowRgn设置窗口显示区域
函数定义:int
SetWindowRgn(
HWND hWnd,//要设置的窗口句柄
HRGN hRgn,//区域句柄,设置的窗口显示区域将由区域句柄决定。
BOOL bRedraw//指明窗口是否重画,true重画
);
SetWindowRgn函数用于设置一个窗口的显示区域,所以必须提供给这个函数一个区域,而该函数的第二个参数hRgn就指明了这个区域。
区域句柄可以通过CreateRectRgn函数(创建一个矩形区域)获取。类似的函数还有CreateEllipticRgn(创建一个圆形区域)。
例子:让一个窗口只显示其四分之一,(什么窗口为例就不需要说了吧)
#include<windows.h>
int main()
{
HWND wnd=::FindWindow(NULL,"无标题.txt - 记事本");
RECT rect;
GetWindowRect(wnd,&rect);//整个窗口,不是客户区域
int Width=rect.right-rect.left;
int Height=rect.bottom-rect.top;
HRGN hRgn=::CreateRectRgn(0,0,Width/4,Height/4);//有兴趣的朋友可以把这句的CreateRectRgn函数换成CreateEllipticRgn试试
SetWindowRgn(wnd,hRgn,true);
return 0;
}
怎么样,窗口是不是只显示了四分之一,但此时用GetClientRect函数获得窗口大小是多少呢,窗口的大小依旧没变,跟原来的一样
SetWindowRgn函数只是设置窗口显示区域,并不是设置窗口大小.
那要如何获得窗口显示区域部分呢,用GetWindowRgn函数,该函数获取窗口显示区域句柄。
第九十五个CombineRgn合并两个区域
函数定义:int
CombineRgn(
HRGN hDestRgn, //接收新区域的句柄
HRGN hSrcRgn1,//要合并的区域句柄1
HRGN hSrcRgn2//要合并的区域句柄2
int nCombineMode//指明具体如何合并
);
这里要注意参数hDesRgn,必须是一个已创建的区域句柄
下面是nCombineMode参数的取值以及各取值所获取的部分
RGN_AND 两个区域的重叠部分
RGN_OR 组合两个区域
RGN_DIFF hSrcRgn1未重叠的部分
RGN_XOR hSrcRgn1和hSrcRgn2未重叠的部分
RGN_COPY 拷贝hSrcRgn1(hSrcRgn1部分)
例子:用FillRgn函数填充两个区域的共同部分
#include<windows.h>
int main()
{
HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
HDC dc=GetDC(wnd);
HRGN hRect=CreateRectRgn(0,0,200,200);
HRGN hElliptic=CreateEllipticRgn(100,100,250,250);
HRGN ComRgn=CreateRectRgn(0,0,0,0);
CombineRgn(ComRgn,hRect,hElliptic,RGN_AND );
while(1)
{
FillRgn(dc,ComRgn,CreateSolidBrush(RGB(255,0,0)));//调用FillRgn函数填充区域
Sleep(300);
}
return 0;
}
第九十六个GetPixel根据DC获取一个坐标点的颜色值
该函数第一个参数,是DC,后两个参数指明坐标点,函数返回该坐标点的颜色值,在这里要说明的是,最好不要直接获取DC里颜色值,用CreateCompatibleDC函数创造一个兼容的DC,然后再用BitBlt函数把DC里的数据复制到兼容的DC里,再用GetPixel函数获取兼容DC里的颜色值。这样的话,就不会出什么问题。
如:
HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
HDC dc=GetDC(wnd);
HDC memDC=CreateCompatibleDC(dc);
RECT rect;
GetClientRect(wnd,&rect);
HBITMAP bmp;
bmp=CreateCompatibleBitmap(dc,rect.right,rect.top);
SelectObject(memDC,bmp);
BitBlt(memDC,0,0,rect.right,rect.top,dc,0,0,SRCCOPY);
COLORREF clr=GetPixel(memDC,10,10);//获取客户区坐标点10.10的颜色值
例子:不规则位图窗口
说明:
要创建一个不规则的位图窗口,首先必须得获得这个不规则位图的区域,是用什么方法呢,大家看一下StretchBlt函数里的flower1位图,
花部分是黑色,其它部分是白色,这样我们可以用GetPixel函数判断哪些像素是黑色,知道了哪些像素是黑色,我就是可以用CreateRectRgn函数创建一个像素区域的区域句柄,再用CombineRgn函数把这个区域添加到一个主区域里。这样就可以获取花部分的区域了
代码如下:(以StretchBlt函数里的两副位图为例)
#include<windows.h>
int main()
{
HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
HBITMAP hBmp1=(HBITMAP)LoadImage(NULL,"e:\\flower1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
HBITMAP hBmp2=(HBITMAP)LoadImage(NULL,"e:\\flower2.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
BITMAP bmInfo;
GetObject(hBmp1,sizeof(BITMAP),&bmInfo);
::MoveWindow(wnd,0,0,bmInfo.bmWidth,bmInfo.bmHeight,TRUE);
HRGN bmRGN=CreateRectRgn(0,0,0,0);
HDC dc=GetWindowDC(wnd);
HDC memDC;
memDC=CreateCompatibleDC(dc);
SelectObject(memDC,hBmp1);
for(int y=0;y<bmInfo.bmHeight;y++)
for(int x=0;x<bmInfo.bmWidth;x++)
{
if(GetPixel(memDC,x,y)==0)//如果是黑色
{
HRGN pRgn=CreateRectRgn(x,y,x+1,y+1);//创建区域
CombineRgn(bmRGN,bmRGN,pRgn,RGN_OR);//把pRgn添加到bmRGN区域里
}
}
SetWindowRgn(wnd,bmRGN,TRUE);
while(1)
{
SelectObject(memDC,hBmp1);
StretchBlt(dc,0,0,bmInfo.bmWidth,bmInfo.bmHeight,memDC,
0,0,bmInfo.bmWidth,bmInfo.bmHeight,SRCAND);//按位与运算合并DC
SelectObject(memDC,hBmp2);
StretchBlt(dc,0,0,bmInfo.bmWidth,bmInfo.bmHeight,memDC,
0,0,bmInfo.bmWidth,bmInfo.bmHeight,SRCPAINT);//按位或运算合并DC
Sleep(300);
}
return 0;
}
运行效果:
对应的函数还有SetPixel这个是设置一个像素点的颜色值
第九十七个PathToRegion将一个DC里的路径转换成选区(HRGN)
函数只有一个参数,是转换路径的DC,函数返回区域句柄。
例子:设置一个文字窗口
#include<windows.h>
int main()
{
HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
HFONT Font=CreateFont(60,60,0,0,FW_NORMAL,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,
"宋体");//创建一种字体
HDC dc=GetDC(wnd);
BeginPath(dc);//请求路径
SelectObject(dc,Font);
SetBkMode(dc,TRANSPARENT);
TextOut(dc,0,0,"文字窗口",8);//形成路径
EndPath(dc);//结束路径
HRGN rgn=::PathToRegion(dc);//将路径转换成选区,rgn接收该区域
SetWindowRgn(wnd,rgn,TRUE);//设置窗口显示区域
return 0;
}
第九十八个GetWindowLong获取一个窗口的信息
函数定义:LONG GetWindowLong (HWND hWnd,int nlndex);
第二个参数nIndex指明获取窗口什么信息,它可以有以下取值:(来自百度百科)
GWL_EXSTYLE;获得扩展窗口风格 对应着CreateWindowEx函数的DWORD wExStyle参数
GWL_STYLE:获得窗口风格 对应着CreateWindowEx函数的DWORD dwStyle参数
GWL_WNDPROC:获得窗口过程的地址,对应着WNDCLASS结构的 pfnWndProc成员
GWL_HINSTANCE WNDCLASS结构的hInstance成员
GWL_HWNDPAAENT:如果父窗口存在,获得父窗口句柄。
GWL_ID:获得窗口标识(窗口ID)
函数的返回值指明窗口信息,依据nIndex取值而定
第九十八个SetWindowLong设置一个窗口信息
函数定义:LONG SetWindowLong(HWND hWnd,int nlndex,LONG dwNewLong);
nIndex参数的解释跟GetWindowLong函数的nIndex参数一样,dwNewLong参数指明要设置的信息,跟GetWindowLong函数的返回值相对应。
例子:去掉一个窗口的标题栏
#include<windows.h>
int main()
{
HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
LONG dw=GetWindowLong(wnd,GWL_STYLE);//获取窗口风格
dw^=WS_CAPTION;//去掉dw的WS_CAPTION(标题)属性
SetWindowLong(wnd, GWL_STYLE,dw); //设置窗口风格
ShowWindow(wnd,SW_MINIMIZE);//最小化窗口
return 0;
}
第九十九个CreateFileMapping创建一个内存文件映射或共享内存(函数返回文件映射对象句柄)
将一个文件映射到内存,对映射的这块内存的读写,就跟磁盘中的文件读写是一样的,由于文件内存映射处理磁盘的文件时,省去了文件I/O操作,因此特别适合处理较大的文件。
函数定义:HANDLE
CreateFileMapping(
HANDLE hFile,//要映射的文件句柄,通过CreateFile函数获得,如果为INVALID_HANDLE_VALUE,则表明创建的是共享内存
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,//它指明返回的句柄是否可以被子进程所继承,一般为NULL
DWORD flProtect,//指明映射打开方式,PAGE_READONLY(只读),PAGE_READWRITE(读写)
DWORD dwMaximumSizeHigh,//文件映射的最大长度的高32位
DWORD dwMaximumSizeLow,//文件映射的最大长度的低32位,
LPCWSTR lpName//文件内存映射对象的名称,可以为NULL
);
由于文件的在最大长度可能会超过32位大小,所以这个函数用两个32位变量(dwMaximumSizeHigh和dwMaximumSizeLow)来表示一个文件的最大长度,当这两个参数的取值都为0时,也就是文件最大长度为0时,就用磁盘文件的实际长度。
第一百个MapViewOfFile将一个文件映射对象映射到当前应用程序的地址空间
函数定义:LPVOID
MapViewOfFile(
HANDLE hFileMappingObject,//文件映射对象的句柄,CreateFileMapping函数获得
DWORD dwDesiredAccess,//映射方式,FILE_MAP_WRITE (读写)FILE_MAP_READ(只读)
DWORD dwFileOffsetHigh,//文件中映射起点的高32位地址
DWORD dwFileOffsetLow,//文件中映射起点的低32位地址 ,高低可为0
DWORD dwNumberOfBytesToMap//文件中要映射的字节数。为0映射整个文件映射对象
);
函数返回文件映射在内存中的起始地址。
例子:读写一个文件(假设E盘下有一个名为a.txt的文件,内容为0123456789)
#include<windows.h>
#include<stdio.h>
int main()
{
HANDLE hFile = CreateFile("e:\\a.txt", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);//以读写方式打开文件
HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE , NULL, NULL, NULL);
LPVOID lpBase = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
for(int i=0;i<10;i++)//读映射内存中的数据
printf("%c ",((char *)lpBase)[i]);
printf("\n");
for(i=0;i<10;i++)//写入数据到映射内存中
((char *)lpBase)[i]=L'A'+i;
return 0;
}
此时再去打开E盘下a.txt文件,是不是里面的内容全变为"A"了。
这里要说明的是,文件打开方式,映射打开方式,映射方式必须是一致的,不能以只读打开文件,又以只写映射打开文件