有些重复的点击是需要做的.但是有时这些点击是不需要看着操作.所以把该窗口切换到前台再去点击让我te不爽.于是写了这么个东西来方便方便.
比如我自己写的试听清风网站的dj音乐这种东西.是需要发现这个歌曲不好听就换下首的,直到找到我喜欢的歌曲才去看它一下,那么这个程序可以帮我设定一个热键,我按一下它就换下首,因为这个程序把这个热键转发到我那个听音乐程序上了,我只需要处理一下这个按钮事件就可以了.而也因为html+js是无法设置全局热键的.所以它们俩配合起来特别好用.
应用.在js代码中编写处理ctrl+q的代码是后首,然后指定接受的窗口到这个页面(必须指向到文档的窗口,指向ie框架的窗口是无效的),把所有的窗口最小化,在进行其它操作时都可以按一下CTRL+q来换到下首了.非常方便.
代码/程序下载 https://skydrive.live.com/?cid=0c051e9a0a1fd5a3&sc=documents&id=C051E9A0A1FD5A3%21536#
更新:
1. 增加允许设置alt做为控制键,因为ctrl键应用上比较多,转发此键将触发其它操作,二个控制键一只手按不了,不考虑使用
--------c语言代码,就一个文件,ide是dev c++-----------------------------
#include <windows.h>
/*
* ini解析模块
* 下载地址:http://ndevilla.free.fr/iniparser/
* 使用方式:解压后把src中的所有文件复制到本工程中的iniparser目录中
* 接着把里面的c后缀文件添加到工程中,否则会出现链接不了的问题
* 可以把这些c加入工程中的一个目录下面也行
*/
#include "./iniparser/iniparser.h"
#define INI_NAME "keys.ini" /* 写死配置文件名 */
#define KEYTABLELEN sizeof keyTable / sizeof keyTable[0]
/*
* 函数声明部分
*/
void create_default_ini_file(char *ini_name);
void parse_ini_file(char * ini_name,HWND hwnd);
void regHotKey(HWND hwnd, char *ini, int ctrlKey);
void delHotKey(HWND hwnd);
UINT findVkey(char *temp, int len);
void sendKeys(HWND rhwnd, LPARAM lParam, HWND hwnd);
struct{
char *name; /* 用于配置中的按键自定义命名*/
UINT VKCode; /* 实际按键的虚拟码 ,查看msdn的虚拟码表即可得到 */
}keyTable[] = {/* 有些使用少的不需要做为热键 */
"space", VK_SPACE,
"pageup", VK_PRIOR,
"pagedown", VK_NEXT,
"end", VK_END,
"home", VK_HOME,
"left", VK_LEFT,
"up", VK_UP,
"right", VK_RIGHT,
"down", VK_DOWN,
"insert", VK_INSERT,
"delete", VK_DELETE,
"0", 0x30,
"1", 0x31,
"2", 0x32,
"3", 0x33,
"4", 0x34,
"5", 0x35,
"6", 0x36,
"7", 0x37,
"8", 0x38,
"9", 0x39,
"a", 0x41,
"b", 0x42,
"c", 0x43,
"d", 0x44,
"e", 0x45,
"f", 0x46,
"g", 0x47,
"h", 0x48,
"i", 0x49,
"j", 0x4A,
"k", 0x4B,
"l", 0x4C,
"m", 0x4D,
"n", 0x4E,
"o", 0x4F,
"p", 0x50,
"q", 0x51,
"r", 0x52,
"s", 0x53,
"t", 0x54,
"u", 0x55,
"v", 0x56,
"w", 0x57,
"x", 0x58,
"y", 0x59,
"z", 0x5A,
"+", VK_ADD,
"-", VK_SUBTRACT,
".", VK_DECIMAL,
"/", VK_DIVIDE
};/* 按键对应表 */
/*
* 声明结束
*/
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[ ] = "keysWindow";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"通用全局快捷键发送程序", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
544, /* The programs width */
375, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);
UpdateWindow (hwnd) ;
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
/* 消息处理 */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
static HWND mHwnd, bingHwnd;
static int cxChar, cyChar, isDrog = 0;
POINT mmPoint;
int helpWin = 1;
switch (message) {
case WM_CREATE :
cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;
parse_ini_file(INI_NAME, hwnd);/* 启动时载入配置 */
/* 帮助按钮 */
CreateWindow ( TEXT("button"),"使用帮助",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
0, 0,
20 * cxChar, 1 * cyChar,
hwnd, (HMENU) helpWin,
((LPCREATESTRUCT) lParam)->hInstance, NULL) ;
/* 绑定窗口标题指示条 */
bingHwnd = CreateWindow ( TEXT("static"),NULL,
WS_CHILD | WS_VISIBLE | SS_LEFT,
0, 2 * cyChar,
0, 0,
hwnd, (HMENU) 999,
NULL, NULL) ;
return 0 ;
case WM_SIZE:
/* 改变绑定指示条区域大小 */
MoveWindow (bingHwnd, 0, 2 * cyChar, LOWORD (lParam), cyChar, TRUE) ;
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
char gTip[] = "本窗按左键后移到接按键的窗口后松开完成绑定,选定的窗口如下:";
TextOut (hdc, 0, cyChar, gTip, lstrlen(gTip)) ;
char keyTitle[] = TEXT("已生效且会转发的热键如下:");
TextOut (hdc, 0, cyChar * 3, keyTitle, lstrlen(keyTitle)) ;
EndPaint(hwnd, &ps);
return 0;
case WM_COMMAND :
if (helpWin == LOWORD(wParam)){/* 如果是帮助按钮消息显示帮助窗口 */
MessageBox(NULL,"本程序是用来为一些没有全局热键程序设置热键,如给ie设置热键.\n\n"
"使用步骤:\n"
"1. 在本窗口任意一个位置按住鼠标左键不放,并移动到一个你准备用来接受按键的窗口\n"
" 注意,有些窗口并不接受按键的,也就是相当你在该程序的这个位置按相同键时没有效果的话\n"
" 那么你应该移动到此程序的另一个位置试试,直到发现这个按键对它有作用为此.\n"
" 一个更加好的方法是,点一下这个位置,按下你设置的键,看它是不是如预想作用.\n"
"2. 在本程序的目录下的keys.ini中按说明输入你要转发的按键.设置会在下回启动时生效.\n"
"3. 配置文件设定,窗口绑定,把本程序最小化,你会发现在按下设定的键时,它在绑定程序上出现作用了.\n\n"
"为方便自己写的小程序.所以bug很明显\n"
"代码在百度qidizi空间有."
,"使用帮助"
, MB_OK);
}
return 0;
case WM_LBUTTONDOWN :
isDrog = 1; /*取消前面设置的窗口*/
SetCapture (hwnd) ;/* 绑定鼠标到本程序,当鼠标移出本程序窗口区域后还能监控移动消息 */
return 0;
case WM_MOUSEMOVE:
if (! isDrog) return 0;
GetCursorPos (&mmPoint);/* 获取鼠标坐标点 */
mHwnd = WindowFromPoint (mmPoint);/* 坐标点得到窗口句柄 */
char wTitle[256];
SetWindowText(bingHwnd, mHwnd ?
(GetWindowText (mHwnd, wTitle, 100) ? wTitle : "窗口无标题")
: "绑定失败" ); /* 显示当前鼠标指向窗口标题 */
return 0;
case WM_LBUTTONUP:
isDrog = 0;
ReleaseCapture();/* 释放鼠标绑定 */
return 0;
case WM_HOTKEY:
sendKeys(mHwnd, lParam, hwnd);/* 热键消息 */
return 0;
case WM_DESTROY:
delHotKey(hwnd); /* 退出程序需要移除热键,防止占用 */
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
}
void delHotKey(HWND hwnd){
int i = 0, len = KEYTABLELEN;
for (; i < len; i++){
UnregisterHotKey(hwnd, (int)keyTable[i].VKCode);
}
}
/* 创建初始配置文件 */
void create_default_ini_file(char * ini_name)
{
FILE * ini ;
if (_access(ini_name, 0) == 0) {
return; /* 配置文件已存在不需要创建样本 */
}
ini = fopen(INI_NAME, "w");
fprintf(ini,
"#\n"
"# 本文件是全局热键设定(或叫转发键)配置文件\n"
"# 文件名必须是:keys.ini 请不要重命名本文件\n"
"# 如果修改错误,可以删除本文件,让程序重新生成样本后再修改.\n"
"# 配置只有在程序启动时才进行应用,在启动后的配置变动只有重启程序才有效果\n"
"#\n\n"
"# 配置语法:\n"
"# 每个设置占用一行\n"
"# 每行设置如下格式:\n"
"# 控制键名=可配置使用的非控制键名系列[多个键名之间用空格(英文状态下的空格键)隔开,键名英文字母全部小写)].\n"
"# 如下一行表示设置CTRL+a, CTRL+b为热键,将把相同的键转发到指定程序上,也就是当你按下这些键时,指定程序也同时相当在该程序上按下相同的组合键\n"
"# ctrl=a b;这里写本行注释"
"# 可用的控制键名有: ctrl, alt;\n"
"# 可用的组合键如下:\n"
"#\n# ");
int i = 0, len = KEYTABLELEN;
for (; i < len; i++){
fprintf(ini,"%s ", keyTable[i].name);/* 列举可用的组合键到配置说明中 */
}
fprintf(ini,"\n"
"[hotkey]\n"
"alt=;键名之间使用空格(注意不能使用tab)隔开\n"
"ctrl=a b;键名之间使用空格(注意不能使用TAB)隔开\n\n");
fclose(ini);
}
void parse_ini_file(char * ini_name, HWND hwnd){
dictionary * ini;
create_default_ini_file(ini_name);
ini = iniparser_load(ini_name);
if (ini==NULL) {
MessageBox(NULL,ini_name, "打开以下配置文件失败, 无法注册热键,请关闭程序", MB_OK);
return;
}
regHotKey(hwnd, iniparser_getstring(ini, "hotkey:alt", ""), MOD_ALT);
regHotKey(hwnd, iniparser_getstring(ini, "hotkey:ctrl", ""), MOD_CONTROL);
iniparser_freedict(ini);/* 必须用完才能释放,否则上面的keys将也被清空 */
}
void regHotKey(HWND hwnd, char *keys, int ctrlKey){
int keyVk, maxName = 20, copy, tlen = KEYTABLELEN;
static keyI = 0;
int cyChar = HIWORD (GetDialogBaseUnits ()), cxChar = LOWORD(GetDialogBaseUnits());
char temp[maxName + 1], msg[maxName + 500];
while(*(keys) != '\0'){/* 未结束 */
copy = 0;
while(*(keys) != '\0'){
if (*(keys) == ' '){
if (copy == 0){/* 名前空格跳过 */
keys++;
continue;
}else if (copy + 1 >= maxName){/* 过长忽略 */
keys++;
copy = 0;/* 丢弃上个名,取下个名 */
continue;
}else{/* 取完整名 */
break;
}
}else if (copy + 1 >= maxName){/* key name 超过长度,直接忽略,注意保留最后一位做\0 */
keys++;/* 忽略 */
continue;
}
temp[copy++] = *(keys), keys++;
}
temp[copy] = '\0';/* 必须正确结束字符串 */
keyVk = findVkey(temp, tlen);
if (0 == keyVk) continue;/* 键码是非0的 */
/* 提示热键注册信息 */
CreateWindow ( TEXT("static"),msg,
WS_CHILD | WS_VISIBLE | SS_LEFT,
0, (keyI + 4) * cyChar,
cxChar * wsprintf(msg, "注册热键[%s + %s]%s;"
, ctrlKey == MOD_ALT ? "ALT" : (ctrlKey == MOD_CONTROL ? "ctrl" : "未知控制键")
, temp,
/* 参数3固定以后值之一:MOD_ALT,MOD_CONTROL,MOD_SHIFT,MOD_WIN*/
/* 参数4必须使用虚拟键码 */
RegisterHotKey(hwnd, (int)keyVk, ctrlKey, keyVk)
? "成功" : "失败:可能是其它程序已经注册了此热键")
, cyChar,
hwnd, (HMENU) keyI,
NULL, NULL) ;
keyI++;
}
}
/* 查找是否允许此自定键名,并返回虚拟码 */
UINT findVkey(char *temp, int len){
int i = 0;
for (; i < len; i++){
if (strcmp(temp, keyTable[i].name) == 0){
return keyTable[i].VKCode;
}
}
return 0;
}
/* 向指定窗口发送按键 */
void sendKeys(HWND rhwnd, LPARAM lParam, HWND hwnd){
if (! rhwnd){
SetWindowText(hwnd, "错误:接收窗口未指定");
return;
}
/*
sizeof CHAR = 1
sizeof BYTE = 1
sizeof WORD = 2
sizeof DWORD = 4
sizeof INT = 4
sizeof LONG = 4
*/
char keyMsg[256];
int sendCtrl, hotCtrl = LOWORD(lParam), hotVKey = HIWORD(lParam);
switch (hotCtrl){
/* 只允许使用ctrl控制键 */
case MOD_CONTROL:
sendCtrl = VK_CONTROL;/* 转化成发送码 */
break;
case MOD_ALT:
sendCtrl = VK_MENU;/* 转化成发送码 */
break;
default:
wsprintf(keyMsg, "转发失败,不允许的控制键码:%d", hotCtrl);
return;
}
WPARAM wCtrl = MAKEWPARAM(sendCtrl, 0), wKey = MAKEWPARAM(hotVKey, 0);
PostMessage(rhwnd, WM_KEYDOWN, wCtrl, 0); /* 模拟按下控制键 */
PostMessage(rhwnd, WM_KEYDOWN, wKey, 0); /* 模拟按下,这里直接转发,不需要转键码*/
Sleep(100); /* 暂停让接收程序足够反应 */
PostMessage(rhwnd, WM_KEYUP, wKey, 0); /* 模拟抬起*/
PostMessage(rhwnd, WM_KEYUP, wCtrl, 0); /* 模拟抬起 控制 键 */
wsprintf(keyMsg, "热键[%d(控制键码), %d(组合键码)],转发[%d(控制键码)+ %d(组合键码)]", hotCtrl, hotVKey, sendCtrl, hotVKey);
SetWindowText(hwnd, keyMsg);
/* 参数3是虚拟键码,4是附加信息,一般是0 */
/*
BOOL WINAPI PostMessage(
__in_opt HWND hWnd,
__in UINT Msg,
__in WPARAM wParam,
__in LPARAM lParam
);
*/
}
标签:VK,return,HWND,hwnd,热键,键盘,ini,转发 From: https://blog.51cto.com/u_252283/6235708