第六十一个GetWindowThreadProcessId根据窗口句柄获得对应进程ID号,和线程ID号
函数只有两个参数,第一个参数是窗口句柄,第二个参数是一个DOWRD类型的指针(进程ID),函数返回线程ID
如:
DWORD ThreadId,ProcessId;
ThreadId=GetWindowThreadProcessId(wnd,&ProcessId);
第六十二个EnumWindows枚举当前正运行的所有主窗口,不包括子窗口
调用这个函数,还必须定义一个回调函数,它的格式是这样的:BOOL CALLBACK lpEnumFunc(HWND wnd, LPARAM lParam);
EnumWindows函数有两个参数,第一个就是回调函数的地址,另一个是自定义参数,对应着回调函数的第二个参数。
每枚举一次窗口,这个回调函数就会被执行一次,而获得的窗口句柄,就会传递给回调函数,对应着回调函数的第一个参数。直到枚举完所有窗口。而在回调用函数里,返回真表示继续枚举,返回假则停止枚举。
例子:枚举窗口
#include<windows.h>
#include<stdio.h>
BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam);
int main()
{
::EnumWindows(lpEnumFunc,0);
return 0;
}
BOOL CALLBACK lpEnumFunc(HWND wnd, LPARAM lParam)
{
char WindowName[52]={0};
GetWindowText(wnd,WindowName,sizeof(WindowName));//根据窗口句柄获得窗口名
printf("窗口句柄:%d 窗口名称:%s\n,",wnd,WindowName);
//可以在这里加个判断当前是否有一个窗口正在运行
//如if(strcmp(WindowName,"Windows 任务管理器")==0) return 0;结束枚举,
return 1;
}
第六十三个MessageBox弹出一个消息提示框
int
MessageBox(
HWND hWnd ,//指明消息框是属于哪个窗口的,可以为NULL
LPCSTR lpText,//消息提示具体内容
LPCSTR lpCaption,//提示框窗口标题
UINT uType);//指明提示框类型,按钮,图标
这里只说下uType的常用可选值:
按钮:
MB_ABORTRETRYIGNORE 终止 重试 忽略
MB_OK 确定
MB_OKCANCEL 确定 取消
MB_RETRYCANCEL 重试 取消
MB_YESNO 是 否
MB_YESNOCANCEL 是 否 取消
图标:
MB_ICONWARNING 感叹号
MB_ICONINFORMATION 提示i
MB_ICONQUESTION 问号
MB_ICONSTOP 红X号
按钮和图标可以结合用,如:
MessageBox(NULL,"该内存不能访问","出错",MB_OK|MB_ICONSTOP);
系统模式:MB_SYSTEMMODAL
函数的返回值确定用户选择了哪个按钮,正面给各按钮的定义:
IDABORT “放弃”按钮
IDCANCEL “取消”按钮
IDIGNORE “忽略”按钮
IDNO “否”按钮
IDOK 确定
IDRETRY 重试
IDYES 是
判断返回值是否与其相等即可。
第六十四个GetForegroundWindow获得当前激活的窗口句柄
函数没参数,调用即返回最前窗口句柄
这里举一个例子:每当切换窗口的时候弹出一个消息提示框
#include<windows.h>
int main()
{
char WindowName[52];
HWND wnd,Orgwnd;
wnd=Orgwnd=NULL;
while(1)
{
wnd=GetForegroundWindow();
if(wnd!=Orgwnd)
{ GetWindowText(wnd,WindowName,sizeof(WindowName));
MessageBox(NULL,WindowName,"切换窗口到",MB_OK);
Orgwnd=wnd;
}
Sleep(200);
}
}
第六十五个GetTopWindow根据窗口句柄获得其下第一子窗口句柄(如果有)
用过MFC的人都知道,在对话编辑区,如果要为控件排序的话,就按CTRL+D显示出每个控件的顺序,如下图:
而GetTopWindow函数获取的就是控件顺序为1的窗口句柄。
例子:改变一个主窗口下的第一子窗口的显示内容(前提得它有),这里就以上面那个abc对话框为例:
#include<windows.h>
int main()
{
HWND wnd;
wnd=FindWindow(NULL,"abc");
HWND FirstWnd=GetTopWindow(wnd);
SetWindowText(FirstWnd,"first");
return 0;
}
执行效果:
第六十六个GetNextWindow根据子窗口句柄获得下一个或上一个同级的窗口句柄(返回NULL,函数执行失败)
函数有两个参数,第一个是子窗口句柄,第二个参数指明寻找上一个,还是一下个窗口句柄,值:GW_HWNONEXT(下一个),GW_HWNDPREV(上一个)。比如子窗口句柄在主窗口的顺序为3,那么获取的是顺序为2或顺序为3的窗口句柄(具体取决于第二个参数),函数返回获得的窗口句柄.这样GetNextWindow结合GetTopWindow函数就可以遍历一个主窗口里的所有子窗口了。
例子:遍历一个窗口里的所有子窗口,以上面的abc窗口为例
#include<stdio.h>
#include<windows.h>
int main()
{
char Name[52];
HWND wnd;
wnd=FindWindow(NULL,"abc");
wnd=GetTopWindow(wnd);
while(wnd!=NULL)
{
GetWindowText(wnd,Name,sizeof(Name));
printf("窗口句柄:%d,名称:%s\n",wnd,Name);
wnd=GetNextWindow(wnd,GW_HWNDNEXT);//GW_HWNDNEXT获取下一个
}
return 0;
}
第六十七个InvalidateRect发送一个WM_PAINT消息给窗口(刷新窗口)
函数定义:BOOL
InvalidateRect(
HWND hWnd ,//要刷新窗口的句柄
CONST RECT *lpRect,//刷新的范围
BOOL bErase//重画为TRUE
);
例子:在SetTimer函数里会举例
第六十八个SetTimer设置一个定时器(每隔一段时间执行一次定时器函数)
函数定义:UINT
SetTimer(
HWND hWnd ,//窗口句柄
UINT nIDEvent,//定时器ID号,为了能设置多个定时器
UINT uElapse,//时间,指明间隔多久执行一次定时器函数,单位:毫秒
TIMERPROC lpTimerFunc);//定时器回调函数的地址
定时器函数的固定格式:VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent, DWORD dwTime);
例子:在用w,a,s,d键控制一个矩形移动的同时,一个相同的矩形自动移动。
#include<windows.h>
LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);//函数声明
VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent, DWORD dwTime);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASS wndcls; //定义一个存储窗口信息WNDCLASS变量
wndcls.cbClsExtra=0; //默认为0
wndcls.cbWndExtra=0; //默认为0
wndcls.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH); //背景画刷
wndcls.hCursor=LoadCursor(NULL,IDC_ARROW); //光标
wndcls.hIcon=LoadIcon(NULL,IDI_ERROR); //窗口图标
wndcls.hInstance=hInstance; //应用程序实例句柄由WinMain函数传进来
wndcls.lpfnWndProc=WinSunProc; //窗口消息处理函数
wndcls.lpszClassName="windowclass"; //窗口类名
wndcls.lpszMenuName=NULL; //窗口菜单名,没有菜单,为NULL
wndcls.style=CS_HREDRAW | CS_VREDRAW;//窗口类型,CS_HREDRAW和CS_VERDRAW 表明
//当窗口水平方向垂直方向的宽度变化时重绘整个窗口
RegisterClass(&wndcls); //把窗口信息提交给系统,注册窗口类
HWND hwnd; //用以存储CreateWindow函数所创建的窗口句柄
hwnd=CreateWindow("windowclass","first windows",
WS_OVERLAPPEDWINDOW,0,0,600,400,NULL,NULL,hInstance,NULL);//创建窗口
ShowWindow(hwnd,SW_SHOWNORMAL);//窗口创建完了,显示它
UpdateWindow(hwnd); //更新窗口,让窗口毫无延迟的显示
SetTimer(hwnd,1,200,(TIMERPROC)TimerProc);//设置定时器
MSG msg;//消息结构类型
while(GetMessage(&msg,NULL,0,0))//获取消息
{
TranslateMessage(&msg); //此函数用于把键盘消息(WM_KEYDOWN,WM_KEYUP)转换成字符消息WM_CHAR
DispatchMessage(&msg); //这个函数调用窗口过程处理函数,并把MSG里的信息处理后传给过程函数的四个参数
}
return 0;
}
VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent, DWORD dwTime)//定时器函数
{
static int x=0,y=0;
x+=15;
if(x>500)
{y+=15;x=0;}
HDC dc=GetDC(hwnd);
Rectangle(dc,x,y,x+30,y+30);
}
LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{ static int x=0,y=0;
switch(uMsg)
{
case WM_CHAR:
{
if(wParam=='a') x-=10;
else if(wParam=='d') x+=10;
else if(wParam=='w') y-=10;
else if(wParam=='s') y+=10;
RECT rect;
GetClientRect(hwnd,&rect);
::InvalidateRect(hwnd,&rect,TRUE);//发送WM_PAINT消息,刷新窗口
}
break;
case WM_PAINT:
HDC dc;
PAINTSTRUCT ps;
dc=BeginPaint(hwnd,&ps); //BeginPaint只能在响应WM_PAINT,不能用GetDC获取设备上下文
Rectangle(dc,x,y,x+30,y+30);
break;
case WM_CLOSE://用户关闭了窗口
DestroyWindow(hwnd);//销毁窗口,并发送WM_DESTROY消息
break;
case WM_DESTROY://如果窗口被销毁
PostQuitMessage(0);//让进程退出
break;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam); //未处理的消息通过DefWindowProc函数交给系统处理
}
第六十九个RegisterHotKey注册一个热键
函数定义:BOOL
RegisterHotKey(
HWND hWnd ,
int id,
UINT fsModifiers,
UINT vk);
第一个参数hWnd表明热键消息(HOT_KEY)发送给哪个窗口,为NULL表明直接把消息投递给调用这个函数进程的消息队列。
第二个参数可以自定取值,取值范围0xC000-0xFFFF,这个参数是为了程序能同时拥有多个热键而存在。
第三个参数fsModifiers的可选取值如下:MOD_ALT(Alt键),MOD_CONTROL(Ctrl键),MOD_SHIFT(Shift键),MOD_WIN(‘田’图标键)
最一个参数是一个ASCII值,指明具体和哪个非系统键组合。
如QQ的热键ctrl+alt+z,注册这个热键的语句是RegisterHotKey(NULL,0x0001,MOD_CONTROL|MOD_ALT,‘Z’)
如QQ的截图热键 RegisterHotKey(NULL,0x0001,MOD_CONTROL|MOD_ALT,'A')
例子:按下ctrl+alt+x热键,弹出消息提示框,询问是否要退出。
//#include "stdafx.h" 新建空工程,不需要该头文件
#include<windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
RegisterHotKey(NULL,0x0001,MOD_CONTROL|MOD_ALT,'X');//注册热键
MSG msg;
while(GetMessage(&msg,NULL,0,0))//从消息队伍获取消息
{
if(msg.message==WM_HOTKEY)//热键消息
{
if(MessageBox(NULL,"你确定要退出程序吗?","热键提示",MB_YESNO|MB_SYSTEMMODAL)==IDYES)
{
UnregisterHotKey(NULL,0x0001);//卸载热键
break;
}
}
}
return 0;
}
记得要退出程序
第七十个StretchBlt在窗口输出一个位图
这个函数比BitBlt多了两个参数,那就是源目标DC的宽高,像BitBlt函数,只有目标DC的宽高。
有了这两个参数的加入,StretchBlt函数功能就比BitBlt函数强大了许多,它可以缩小或放大图片,可以把一张图片上的任意矩形区域覆盖到另一张图片上的任意区域。
函数语句:StretchBlt(hdc,0,0,bmInfo.bmWidth,bmInfo.bmHeight,memDC,0,0,50,50,SRCCOPY);
具体用法参考BitBlt函数。
例子:在窗口输出不规则形状的位图。
说明:
位图其实都是矩形,这里要说的是可以输出位图里的任意形状部分,但位图不输出的部分,必须是固定的颜色
为什么呢?白色的RGB值是255,255,255,把255转换成二进制,可以看到每一位都是1,如:11111111.这样任何一种颜色与白色进行按位与运算,其结果都不会变,这样两个DC合并进行按位与(SRCAND)运算,白色的部分都会被屏蔽,而任何一种颜色与黑色进行按位与运算,其结果都为黑色,与黑色进行按位或(SRCAND)运算,其结果不会改变。黑色的RGB值是0,0,0。
输出这样的图形,要准备两张图片,必须是这种模式,如下:
flower1 flower2
这里要输出在窗口里的是flower2图片里的花,黑色部分不输出
假设这两张图片在E盘,看例子:
#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);
HDC dc=GetDC(wnd);
HDC memDC;
memDC=CreateCompatibleDC(dc);
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(200);
}
}
运行效果如下图: