win32键盘记录 -- 自定义窗口类
最近学了些关于window api编程的知识,于是琢磨编写一些键盘记录器,能够把输入的按键输出到窗口内,并且实现窗口自动滚动。
封装窗口类使用了GWL_USERDATA字段来保存this指针,比较容易理解,缺点如果程序别的地方使用这个字段会引起崩溃...
WinClassBase.h
#ifndef _WINDOW_CLASS_BASE_
#define _WINDOW_CLASS_BASE_ #include <windows.h>
#include <vector>
#include <string> class WinClassBase
{
public:
WinClassBase(HINSTANCE hInastance, HWND HwndParent = NULL, int winLeft=, int winRight=, int winTop=, int winBottom=);
~WinClassBase(); virtual int HandleMessage(UINT message,WPARAM wParam,LPARAM lParam) = ;
virtual LPCTSTR GetMyClassName() = ; //创建窗口
void Create();
//获取窗口句柄
HWND GetMyHandle() const { return m_hWnd; } void ShowWindow(int nShowCmd);
int exec(); protected:
virtual UINT GetMyClassStyle() { return CS_VREDRAW | CS_HREDRAW; }
virtual HICON GetMyClassIcon() { return NULL; }
virtual HCURSOR GetMyClassCursor() { return NULL; }
virtual HBRUSH GetMyClassBackground() { return HBRUSH(COLOR_WINDOW+); }
virtual LPCTSTR GetMyClassMenuName() { return NULL; } virtual LPCTSTR GetMyWindowName() { return TEXT("wuyou"); }
virtual DWORD GetMyWindowStyle() { return WS_OVERLAPPEDWINDOW; }
virtual HMENU GetMyWindowMenu() { return NULL; }
private:
//原始窗口
static LRESULT CALLBACK WindowProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam); protected:
HWND m_hWnd;
HWND m_hWndParent;
RECT m_rect;
HINSTANCE m_hInastance; //已注册过的类的集合
static std::vector<std::wstring> registeredClassArray;
}; #endif //_WINDOW_CLASS_BASE_
WinClassBase.cpp
#include "WinClassBase.h" std::vector<std::wstring> WinClassBase::registeredClassArray; WinClassBase::WinClassBase(HINSTANCE hInastance, HWND hWndParent, int winLeft, int winRight, int winTop, int winBottom)
{
m_hInastance = hInastance; m_hWndParent = hWndParent; m_rect.left = winLeft;
m_rect.right = winRight;
m_rect.top = winTop;
m_rect.bottom = winBottom; m_hWnd = NULL;
} WinClassBase::~WinClassBase(void)
{
if( this->m_hWnd != NULL && ::IsWindow(this->m_hWnd) )
{
::DestroyWindow(this->m_hWnd);
}
} //创建窗口
void WinClassBase::Create()
{
unsigned int i=;
for(i=; i<registeredClassArray.size(); ++i)
{
if( registeredClassArray[i] == std::wstring(this->GetMyClassName()) )
{
break;
}
} //注册
if( i == registeredClassArray.size() )
{
WNDCLASS win; win.cbClsExtra = ;
win.cbWndExtra = ;
win.hbrBackground = this->GetMyClassBackground();
win.hCursor = this->GetMyClassCursor();
win.hIcon = this->GetMyClassIcon();
win.hInstance = m_hInastance;
win.lpfnWndProc = WinClassBase::WindowProc;
win.lpszClassName = this->GetMyClassName();
win.lpszMenuName = this->GetMyClassMenuName();
win.style = this->GetMyClassStyle(); if( != ::RegisterClass(&win))
{
registeredClassArray.push_back(this->GetMyClassName());
}
} //创建窗口
if( NULL == this->m_hWnd )
{
HWND hWnd = ::CreateWindow(this->GetMyClassName(),
this->GetMyWindowName(),
this->GetMyWindowStyle(),
this->m_rect.left,
this->m_rect.top,
this->m_rect.right - this->m_rect.left,
this->m_rect.bottom - this->m_rect.top,
this->m_hWndParent,
this->GetMyWindowMenu(),
this->m_hInastance,
(LPVOID)this
); if(NULL == hWnd)
{
this->m_hWnd = NULL;
WCHAR errorMsg[] = {};
::swprintf(errorMsg, , TEXT("CreateWindow Failed: %ld"), ::GetLastError());
::MessageBox(NULL, errorMsg, TEXT("Error"), MB_OK);
return ;
}
}
} LRESULT CALLBACK WinClassBase::WindowProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
WinClassBase *pThis = NULL; if(message == WM_CREATE)
{
pThis = (WinClassBase *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
pThis->m_hWnd = hwnd;
::SetWindowLong(hwnd, GWL_USERDATA, (LONG)pThis);
} pThis = (WinClassBase *)::GetWindowLong(hwnd, GWL_USERDATA); switch(message)
{
case WM_DESTROY:
PostQuitMessage();
break;
default:
if(pThis != NULL && pThis->HandleMessage(message, wParam, lParam) == )
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
else if(pThis == NULL)
{
return DefWindowProc(hwnd, message, wParam, lParam);
} break;
} return ;
} void WinClassBase::ShowWindow(int nShowCmd)
{
::ShowWindow(this->m_hWnd, nShowCmd);
::UpdateWindow(this->m_hWnd);
}
int WinClassBase::exec()
{
MSG msg; while(::GetMessage(&msg, NULL, NULL, NULL))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
} return ;
}
KeyBoard.h
#pragma once #include "WinClassBase.h" #define MAX_LINE 1000 class KeyBoard : public WinClassBase
{
public:
KeyBoard(HINSTANCE hInastance, HWND HwndParent = NULL, int winLeft=, int winRight=, int winTop=, int winBottom=);
~KeyBoard(void); virtual int HandleMessage(UINT message,WPARAM wParam,LPARAM lParam);
virtual LPCTSTR GetMyClassName(); virtual DWORD GetMyWindowStyle() { return WS_OVERLAPPEDWINDOW | WS_VSCROLL; }
virtual LPCTSTR GetMyWindowName() { return TEXT("键盘记录"); } private:
int m_line;
TEXTMETRIC m_textMetric;
SCROLLINFO m_scrollinfo; TCHAR m_charArray[MAX_LINE][];
};
KeyBoard.cpp
#include "KeyBoard.h"
#include <wchar.h> KeyBoard::KeyBoard(HINSTANCE hInastance, HWND hWndParent, int winLeft, int winRight, int winTop, int winBottom)
:WinClassBase(hInastance, hWndParent, winLeft, winRight, winTop, winBottom)
{
} KeyBoard::~KeyBoard(void)
{
} int KeyBoard::HandleMessage(UINT message,WPARAM wParam,LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
{
HDC hdc = GetDC(m_hWnd);
::GetTextMetrics(hdc, &m_textMetric);
ReleaseDC(m_hWnd, hdc);
m_scrollinfo.cbSize = sizeof(m_scrollinfo);
m_scrollinfo.nMax = MAX_LINE - ;
m_scrollinfo.nMin = ;
m_scrollinfo.nPos = ;
m_line = ; return ;
}
case WM_SIZE:
{
WORD newHeight = HIWORD(lParam);
m_scrollinfo.nPage = newHeight / m_textMetric.tmHeight;
m_scrollinfo.fMask = SIF_ALL;
::SetScrollInfo(m_hWnd, SB_VERT, &m_scrollinfo, TRUE); return ;
}
case WM_VSCROLL:
{
switch(LOWORD(wParam))
{
case SB_BOTTOM:
m_scrollinfo.nPos = m_line;
break;
case SB_LINEDOWN:
m_scrollinfo.nPos = (m_scrollinfo.nPos+);
break;
case SB_LINEUP:
if( m_scrollinfo.nPos >= )
m_scrollinfo.nPos = m_scrollinfo.nPos-;
break;
case SB_PAGEDOWN:
m_scrollinfo.nPos += m_scrollinfo.nPage;
break;
case SB_PAGEUP:
m_scrollinfo.nPos -= m_scrollinfo.nPage;
break;
case SB_THUMBPOSITION:
m_scrollinfo.nPos = HIWORD(wParam);
break;
case SB_THUMBTRACK:
m_scrollinfo.nPos = HIWORD(wParam);
break;
} m_scrollinfo.fMask = SIF_POS;
SetScrollInfo(m_hWnd, SB_VERT, &m_scrollinfo, TRUE);
InvalidateRect(m_hWnd, NULL, TRUE); return ;
}
case WM_CHAR:
{
if(m_line < MAX_LINE)
{
wmemset(m_charArray[m_line], , );
swprintf(m_charArray[m_line], , TEXT("wParam = 0x%X lParam = 0x%X val = %c"), wParam, lParam, wParam);
m_line ++; if(m_line >= (int)(m_scrollinfo.nPos + m_scrollinfo.nPage))
::PostMessage(m_hWnd, WM_VSCROLL, SB_PAGEDOWN, );
else
{
RECT rect;
rect.left = ;
rect.right = m_rect.right;
rect.top = ((m_line-) % m_scrollinfo.nPage) * m_textMetric.tmHeight;
rect.bottom = rect.top + m_textMetric.tmHeight;
InvalidateRect(m_hWnd, &rect, TRUE);
}
} return ;
}
case WM_PAINT:
{
PAINTSTRUCT paint;
HDC hdc = ::BeginPaint(m_hWnd, &paint);
for(int i=; i<(int)m_scrollinfo.nPage && i+m_scrollinfo.nPos<MAX_LINE; i++)
{
if( i+m_scrollinfo.nPos >= m_line )
::TextOut(hdc, , i*m_textMetric.tmHeight, TEXT(""), );
else
::TextOut(hdc, , i*m_textMetric.tmHeight, m_charArray[i+m_scrollinfo.nPos], wcslen(m_charArray[i+m_scrollinfo.nPos]));
}
::EndPaint(m_hWnd, &paint);
::ReleaseDC(m_hWnd, hdc);
return ;
}
} return ;
}
LPCTSTR KeyBoard::GetMyClassName()
{
return TEXT("keyBoardClass");
}
main
#include "KeyBoard.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nShowCmd )
{
KeyBoard key(hInstance); key.Create();
key.ShowWindow(nShowCmd); return key.exec();
}
win32键盘记录 -- 自定义窗口类的更多相关文章
- sizzle分析记录: 自定义伪类选择器
可见性 :hidden :visible 隐藏对象没有宽高,前提是用display:none处理的 jQuery.expr.filters.hidden = function( elem ) { // ...
- WPF自定义窗口基类
WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...
- 探索Win32系统之窗口类(转载)
Window Classes in Win32 摘要 本文主要介绍win32系统里窗口类的运做和使用机制,探索一些细节问题,使win32窗口类的信息更加明朗化. 在本文中,"类", ...
- WPF自学入门(九)WPF自定义窗口基类
今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...
- Win32编程:窗口类样式+窗口外观样式+窗口显示样式
1.窗口类样式WNDCLASS.style CS_VREDRAW 提供窗口位置变化事件和高度变化事件的处理程序,功能是重绘窗口 CS_HREDRAW 提供窗口位置变化事件和宽度变化事件的处理程序,功能 ...
- WPF 之 创建继承自Window 基类的自定义窗口基类
开发项目时,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于 Window 自身的,但窗口的外边框及窗口移动.最小化等标题栏操作基本都是一样的.所以通过查看资料,可按如下方法创建继承 ...
- WIN32窗口类风格和窗口风格(备查询)
一.WNDCLASS typedef struct { UINT cbSize //这个结构体的长度,一般用sizeof(WNDCLASSEX)设置 UINT style //窗口式样 WNDPROC ...
- win32程序之子窗口编程
win32程序之子窗口编程 一丶简介.什么是子窗口 在前边我们已经讲解了窗口的本质.以及如何注册窗口类跟创建窗口. 还讲了消息循环. 那么有很多窗口其实Windows已经帮我们创建出来了.我们直接使用 ...
- 【Q2D】如何导出自定义C++类给框架使用
本文基于Quick cocos2d x这个游戏框架,为了行文流畅,后面都简称Q2D 导出自定义c++类给项目使用已经有了现成的例子了 详见:http://quick.cocos.org/?p=235 ...
随机推荐
- 在图层上使用CATransform3D制做三维动画-b
在UIView上,我们可以使用CGAffineTransform来对视图进行:平移(translation),旋转(Rotation),缩 放(scale),倾斜(Invert)操作,但这些操作是没有 ...
- Python的字符串操作和Unicode
字符串类型 str:Unicode字符串.采用''或者r''构造的字符串均为str,单引号可以用双引号或者三引号来代替.无论用哪种方式进行制定,在Python内部存储时没有区别. bytes:二进制字 ...
- Swift 中的 Runtime
即使在 Swift APP 中没有一行 Object-c 的代码,每个 APP 也都会在 Object-c runtime 中运行,为动态任务分发和运行时对象关联开启了一个世界.更确切地说,可能在仅使 ...
- Lucas定理及其应用
Lucas定理这里有详细的证明. 其实就是针对n, m很大时,要求组合数C(n, m) % p, 一般来说如果p <= 10^5,那么就能很方便的将n,m转化为10^5以下这样就可以按照乘法逆元 ...
- 坚果云创业团队访谈:我们 DIY 云存储(不要过度关注竞争对手,尤其当我们还是小公司的时候)
坚果云(http://jianguoyun.com/)是一款用于多平台文件同步.备份和交换的云存储工具,立志于提供“便捷,安全”的服务.坚果云自去年年初启动内测,至今年三月初刚刚正式发布.近日我们拜访 ...
- [OJ] Data Stream Median (Hard)
LintCode 81. Data Stream Median (Hard) 思路: 用一个大根堆保存较小的一半数, 一个小根堆保存较大的一半数. 每次根据num和两个堆顶的数据决定往哪个堆里面放. ...
- chrome插件 postman插件 接口测试、API & HTTP 请求调试工具
Postman 是一个非常棒的Chrome扩展,提供功能强大的API & HTTP 请求调试. 它能够发送任何类型的HTTP requests (GET, HEAD, POST, PUT..) ...
- 浏览器助手,请求拦截,后台模拟键鼠操作,页内嵌入JS
http://www.cnblogs.com/ /// <summary> /// 网页浏览器助手 /// 请求拦截,后台模拟键鼠操作,页内嵌入JS ...
- Python Anaconda2 (64-bit) 安装后启动jupyter-notebook默认目录更改
看了网上很多关于更改 python notebook的,好麻烦,所以想了一招. python notebook 现在改名叫 jupyter-notebook ,被集成在Anaconda中. Anaco ...
- C#常用的命名规范
C#常用的命名规则 Pascal 规则 每个单词开头的字母大写(如 TestCounter). Camel 规则 除了第一个单词外的其他单词的开头字母大写. 如. testCounter. Upper ...