第八十一个WriteFile根据文件句柄,写入一段数据到文件中
函数定义:BOOL
WriteFile(
HANDLE hFile,//文件句柄
LPCVOID lpBuffer,//该缓存区的数据将要写入到文件里
DWORD nNumberOfBytesToWrite,//指明写入多少数据
LPDWORD lpNumberOfBytesWritten,//实际写入数据
LPOVERLAPPED lpOverlapped//一般为NULL
);
例子:在E盘创建一个名为aa.txt的文件,并向其写入数据
#include<windows.h>
#include<stdio.h>
int main()
{
char Text[25]="123456789";
DWORD dwSize;
HANDLE FileHandle=CreateFile("e:\\aa.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,NULL);
::WriteFile(FileHandle,Text,9,&dwSize,0);
return 0;
}
第八十二个SetFilePointer移动一个文件指针的位置
移动一个文件指针的位置有什么用呢,作用是读取一个文件里指定位置的数据,比如我只要读取文件中第四个字节到第七个字节这一段的数据,用SetFilePointer函数就可以完成。
函数定义:DWORD
SetFilePointer(
HANDLE hFile,//文件句柄
LONG lDistanceToMove,//移动字节,负数表示反向移动
PLONG lpDistanceToMoveHigh,//为了支持超大文件而存在,一般为NULL
DWORD dwMoveMethod//从哪里开始移动,FILE_BEGIN 从文件开始处开始移动,FILE_CURRENT当前位置,FILE_END文件末尾
);
例子:假设E盘下有一个名为a.txt的文件,内容为"123456789",读取该文件第四个字节到第七个字节的数据
#include<windows.h>
#include<stdio.h>
int main()
{
char Text[25]={0};
DWORD dwSize;
HANDLE FileHandle=CreateFile("e:\\a.txt",GENERIC_READ,0,NULL,OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(FileHandle,3,NULL,FILE_BEGIN);
ReadFile(FileHandle,Text,4,&dwSize,NULL);
printf("%s\n",Text);
return 0;
}
例子2:从文件中第四个字节开始写入数据,被新数据所占位置的数据会被覆盖掉,依旧以上面a.txt文件为例子
#include<windows.h>
#include<stdio.h>
int main()
{
char Text[25]={"abcd"};
DWORD dwSize;
HANDLE FileHandle=CreateFile("e:\\a.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,NULL);
SetFilePointer(FileHandle,3,NULL,FILE_BEGIN);
WriteFile(FileHandle,Text,4,&dwSize,NULL);
return 0;
}
则写入后a.txt文件里的数据为123abcd89
如果要在文件的末尾添加数据,就用这个语句:SetFilePointer(FileHandle,0,NULL,FILE_END);
第八十三个GetFileSize获取一个文件的大小
函数定义:DWORD
GetFileSize(
HANDLE hFile,//文件句柄
LPDWORD lpFileSizeHigh//一般为NULL
);
如获取a.txt文件的大小:
#include<windows.h>
#include<stdio.h>
int main()
{
DWORD FileSize;
HANDLE FileHandle=CreateFile("e:\\a.txt",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,NULL);
FileSize=GetFileSize(FileHandle,NULL);
printf("%d字节\n",FileSize);
return 0;
}
第八十四个SetTextColor设置窗口输出文本颜色
第一个参数是设备DC,第二个参数是一个COLORREF类型的颜色值,可用RGB进行转换。
第八十五个SetBkColor设置背景颜色
参数跟SetTextColor函数一样,第一个DC,第二个COLORREF
第八十六个GetWindowDC获取整个窗口设备上下文DC
像GetDC获取的只是客户区DC,不能对窗口标题栏,状态栏等进行操作。该函数用法跟GetDC一样,仅区域不一样。
例子:在一个窗口的标题栏输出文字
#include<windows.h>
int main()
{
HWND wnd=FindWindow(NULL,"无标题.txt - 记事本");
HDC dc=GetWindowDC(wnd);
SetTextColor(dc,RGB(255,0,0));//文本颜色设置为红色
::SetBkColor(dc,RGB(0,0,255));//文本背景颜色设置为蓝色
while(1)
{
TextOut(dc,0,0,"123456",6);
Sleep(200);
}
return 0;
}
第八十七个GetDesktopWindow获取桌面窗口句柄
该函数没有参数,调用返回桌面窗口句柄
例子:
#include<windows.h>
int main()
{
HWND DeskWnd=GetDesktopWindow();//获取桌面窗口句柄
HDC DeskDC=GetWindowDC(DeskWnd);//获取DC
HBRUSH brush=::CreateSolidBrush(RGB(255,0,0));//红色画刷
SelectObject(DeskDC,brush);//选入画刷
while(1)
{
::Rectangle(DeskDC,50,50,200,200);
Sleep(200);
}
return 0;
}
第八十八个CreateCompatibleBitmap根据DC创造一个兼容的位图
该函数需与CreateCompatibleDC函数配合使用
函数第一个参数是窗口DC,第二,三参数指明窗口宽高,函数返回位图句柄(HBITMAP)
创建一个兼容的位图是什么意思呢?就好比给HBITMAP分配内存以及指定这位图相关的一些信息(跟DC相关的信息),如位图的宽高,数据大小,但此时数据没有具体取值。就好比一个字符串,我已经知道字符串大小了,但却不知道字符串具体是什么:
如:
char *p;
p=new char[15];//知道字符串大小为15
但此时p所指向的缓存区,没有具体取值。
而用CreateCompatibleBitmap函数,创建的位图,只是一个空壳子。数据没有赋值,那要怎样给数据赋值呢?
首先得把这个位图句柄选入一个DC(该DC必须为CreateCompatibleDC函数创建的)里,然后再用BitBlt函数具体给数据赋值就行了。
例子:实时获取屏幕图像
为了方便,在记事本窗口输出图像,自己就不创建窗口了(打开"无标题.txt - 记事本")
#include<windows.h>
int main()
{
HWND TextWnd=FindWindow(NULL,"无标题.txt - 记事本");
HDC TextDC=GetDC(TextWnd);
HWND DeskWnd=::GetDesktopWindow();
RECT DeskRC;
::GetClientRect(DeskWnd,&DeskRC);
HDC DeskDC=GetDC(DeskWnd);
HBITMAP DeskBmp=::CreateCompatibleBitmap(DeskDC,DeskRC.right,DeskRC.bottom);
HDC memDC;
memDC=::CreateCompatibleDC(DeskDC);
SelectObject(memDC,DeskBmp);
while(1)
{
StretchBlt(memDC,0,0,DeskRC.right,DeskRC.bottom,DeskDC,0,0,DeskRC.right,DeskRC.bottom,SRCCOPY);
RECT TextRC;
GetClientRect(TextWnd,&TextRC);
::StretchBlt(TextDC,0,0,TextRC.right,TextRC.bottom,memDC,0,0,DeskRC.right,
DeskRC.bottom,SRCCOPY);
Sleep(300);
}
return 0;
}
第八十九个GetDIBits从一个兼容位图里获取位图数据
先来分析一下位图文件信息结构,一个位图由以下四部分组成:
位图文件头(BITMAPFILEHEADER)//占14字节
位图信息头(BITMAPINFOHEADER)//占40字节
调色板(LOGPALLETE)//如果是真彩位图,那该部分没有,直接是位图数据
实际位图数据
而GetDIBits函数获取的就是实际位图数据这一部分了。
接来看一下BITMAPFILEHEADER这个结构以及它成员的意思和取值
typedef struct tagBITMAPFILEHEADER {
WORD bfType;//表示文件类型,值必须为0x4d42
DWORD bfSize;//文件的大小
WORD bfReserved1;//保留,必须为0
WORD bfReserved2;//保留,必须为0
DWORD bfOffBits;//位图前三部分所占的字节,真彩色位图为54
} BITMAPFILEHEADER;
上面的成员,只有bfSize的取值不确定,其它都一样,也就是说,每个真彩位图,这几个成员取值都是一样的.下面的例子可以说明。
读取一个真彩位图的文件信息头。
#include<windows.h>
#include<stdio.h>
int main()
{
BITMAPFILEHEADER bfh;
HANDLE hFile=CreateFile("e:\\aa.bmp",GENERIC_READ,0,NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,0);
DWORD dwSize;
ReadFile(hFile,(void *)&bfh,sizeof(BITMAPFILEHEADER),&dwSize,0);
printf("bfType:%x\n",bfh.bfType);
printf("bfSize:%d\n",bfh.bfSize);
printf("bfReserved1:%d\n",bfh.bfReserved1);
printf("bfReserved2:%d\n",bfh.bfReserved2);
printf("bfOffbits:%d\n",bfh.bfOffBits);
return 0;
}
再来看一下BITMAPINFOHEADER这个结构以及它成员的意思和取值
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;//本结构大小,为40
LONG biWidth;//位图的宽度,以像素为单位
LONG biHeight;//位图的高度,以像素为单位
WORD biPlanes;//目标设备的级别,必须是1
WORD biBitCount;//每个像素所占的位数,24表示真彩位图
DWORD biCompression;//位图压缩类型,一般为BI_RGB(未经压缩)
DWORD biSizeImage;//实际位图数据所占用的字节数
LONG biXPelsPerMeter;//指定目标设备水平分辨率,单位像素/米,为0
LONG biYPelsPerMeter;//指定目标垂直分辨率真,单位像素/米,为0
DWORD biClrUsed;//指定目标设备实际用到的颜色数,如果该值为0,则用到的颜色数为2的biBitCount方
DWORD biClrImportant;//表示图像中重要的颜色数,如果为0,则所有颜色都是重要的。
} BITMAPINFOHEADER;
调色板(LOGPALLETE)由于大部分都是针对真彩位图操作,此部分略过
GetDIBits函数定义:int GetDIBits(
HDC hdc, //位图兼容的DC
HBITMAP hbmp, //位图句柄
UINT uStartScan, //从哪行开始扫描
UINT cScanLines, //扫描多少行数据
LPVOID lpvBits, //接收数据的缓存区
LPBITMAPINFO lpbi, //真彩位图,此处填位图信息头就行了
UINT uUsage//真彩位图填DIB_RGB_COLORS,表示由R,G,B三色直接构成
);
例子:截屏,并把屏幕图片保存成位图
#include<windows.h>
void ScreenSnap(HBITMAP hBitmap,char *bmpPath,HDC dc);
int main()
{
HWND DeskWnd=::GetDesktopWindow();//获取桌面窗口句柄
RECT DeskRC;
::GetClientRect(DeskWnd,&DeskRC);//获取窗口大小
HDC DeskDC=GetDC(DeskWnd);//获取窗口DC
HBITMAP DeskBmp=::CreateCompatibleBitmap(DeskDC,DeskRC.right,DeskRC.bottom);//兼容位图
HDC memDC=::CreateCompatibleDC(DeskDC);//兼容DC
SelectObject(memDC,DeskBmp);//把兼容位图选入兼容DC中
BitBlt(memDC,0,0,DeskRC.right,DeskRC.bottom,DeskDC,0,0,SRCCOPY);//拷贝DC
ScreenSnap(DeskBmp,"d:\\Screen.bmp",DeskDC);
return 0;
}
void ScreenSnap(HBITMAP hBitmap,char *bmpPath,HDC dc)
{
BITMAP bmInfo;
DWORD bmDataSize;
char *bmData;//位图数据
GetObject(hBitmap,sizeof(BITMAP),&bmInfo);//根据位图句柄,获取位图信息
bmDataSize=bmInfo.bmWidthBytes*bmInfo.bmHeight;//计算位图数据大小
bmData=new char[bmDataSize];//分配数据
BITMAPFILEHEADER bfh;//位图文件头
bfh.bfType=0x4d42;
bfh.bfSize=bmDataSize+54;
bfh.bfReserved1=0;
bfh.bfReserved2=0;
bfh.bfOffBits=54;
BITMAPINFOHEADER bih;//位图信息头
bih.biSize=40;
bih.biWidth=bmInfo.bmWidth;
bih.biHeight=bmInfo.bmHeight;
bih.biPlanes=1;
bih.biBitCount=24;
bih.biCompression=BI_RGB;
bih.biSizeImage=bmDataSize;
bih.biXPelsPerMeter=0;
bih.biYPelsPerMeter=0;
bih.biClrUsed=0;
bih.biClrImportant=0;
::GetDIBits(dc,hBitmap,0,bmInfo.bmHeight,bmData,(BITMAPINFO *)&bih,DIB_RGB_COLORS);//获取位图数据部分
HANDLE hFile=CreateFile(bmpPath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,0);//创建文件
DWORD dwSize;
WriteFile(hFile,(void *)&bfh,sizeof(BITMAPFILEHEADER),&dwSize,0);//写入位图文件头
WriteFile(hFile,(void *)&bih,sizeof(BITMAPINFOHEADER),&dwSize,0);//写入位图信息头
WriteFile(hFile,(void *)bmData,bmDataSize,&dwSize,0);//写入位图数据
::CloseHandle(hFile);//关闭文件句柄
}
第九十个FindWindowEx查找一个父窗口里的子窗口(根据子窗口类名,窗口名),函数返回子窗口句柄
函数定义:HWND FindWindowEx
(HWND hwndParent,//父窗口句柄
HWND hwndChildAfter,//子窗口句柄,指明Z序
LPCTSTR lpszClass,//窗口类名
LPCTSTR lpszWindow//窗口名称
);
第一个参数hwndParent如果为NULL,则以桌面窗口为父窗口,此时,这个函数与FindWindow函数一样,
第二个参数,子窗口句柄,如果为NULL,则从主窗口的第一Z序开始查找,否则从该子窗口的Z序开始查找。
后面两个个参数跟FindWindow的两个参数意思一样。
例子:模仿按钮单击
查找一个父窗口下特定的按钮,然后用SendMessage函数给父窗口发送按钮被单击的消息
假设这个父窗口名为"abc",其下有一个名为"确定"的按钮
提示:
控件消息是:WM_COMMAND,wParam参数低十六位存储存控件ID号,高十六位存储有具体控件消息(如BN_CLICKED,单击),lParam存储控件窗口句柄,控件ID号可以用GetDlgCtrlID函数获取,该函数根据控件窗口句柄,获取控件ID号。
#include<windows.h>
int main()
{
HWND wnd=::FindWindow(NULL,"abc");
HWND ButtonWnd=::FindWindowEx(wnd,NULL,NULL,"确定");//查找名为"确定"的子窗口句柄
int CtrlID=::GetDlgCtrlID(ButtonWnd);//获得控件ID
SendMessage(wnd,WM_COMMAND,MAKEWPARAM(CtrlID,BN_CLICKED),LPARAM(ButtonWnd));//发送控件消息
return 0;
}