最近学了些关于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键盘记录 -- 自定义窗口类的更多相关文章

  1. sizzle分析记录: 自定义伪类选择器

    可见性 :hidden :visible 隐藏对象没有宽高,前提是用display:none处理的 jQuery.expr.filters.hidden = function( elem ) { // ...

  2. WPF自定义窗口基类

    WPF自定义窗口基类时,窗口基类只定义.cs文件,xaml文件不定义.继承自定义窗口的类xaml文件的根节点就不再是<Window>,而是自定义窗口类名(若自定义窗口与继承者不在同一个命名 ...

  3. 探索Win32系统之窗口类(转载)

    Window Classes in Win32 摘要 本文主要介绍win32系统里窗口类的运做和使用机制,探索一些细节问题,使win32窗口类的信息更加明朗化. 在本文中,"类", ...

  4. WPF自学入门(九)WPF自定义窗口基类

    今天简单记录一个知识点:WPF自定义窗口基类,常用winform的人知道,winform的窗体继承是很好用的,写一个基础窗体,直接在后台代码改写继承窗体名.但如果是WPF要继承窗体,我个人感觉没有理解 ...

  5. Win32编程:窗口类样式+窗口外观样式+窗口显示样式

    1.窗口类样式WNDCLASS.style CS_VREDRAW 提供窗口位置变化事件和高度变化事件的处理程序,功能是重绘窗口 CS_HREDRAW 提供窗口位置变化事件和宽度变化事件的处理程序,功能 ...

  6. WPF 之 创建继承自Window 基类的自定义窗口基类

    开发项目时,按照美工的设计其外边框(包括最大化,最小化,关闭等按钮)自然不同于 Window 自身的,但窗口的外边框及窗口移动.最小化等标题栏操作基本都是一样的.所以通过查看资料,可按如下方法创建继承 ...

  7. WIN32窗口类风格和窗口风格(备查询)

    一.WNDCLASS typedef struct { UINT cbSize //这个结构体的长度,一般用sizeof(WNDCLASSEX)设置 UINT style //窗口式样 WNDPROC ...

  8. win32程序之子窗口编程

    win32程序之子窗口编程 一丶简介.什么是子窗口 在前边我们已经讲解了窗口的本质.以及如何注册窗口类跟创建窗口. 还讲了消息循环. 那么有很多窗口其实Windows已经帮我们创建出来了.我们直接使用 ...

  9. 【Q2D】如何导出自定义C++类给框架使用

    本文基于Quick cocos2d x这个游戏框架,为了行文流畅,后面都简称Q2D 导出自定义c++类给项目使用已经有了现成的例子了 详见:http://quick.cocos.org/?p=235 ...

随机推荐

  1. Jfinal 入门

    Jfinal 入门 IDE----->IDEA 新建项目 新建web项目 添加maven特性 方便导入jar包,不用一个个导入了 配置pom.xml <dependencies> & ...

  2. office2016 部分截图

    哈啊哈哈啊哈 看看吧~~~~~~~~~~~~~~~~~

  3. C# const和statci readonly区别

    1.const 是属于编译时的变量,它定义的常量是在对象初始化时赋值,以后不能改变他的值. 它适用于两种场景:1.取值永久不变(比如圆周率.一天包含的小时数.地球的半径等)  2.对程序性能要求非常苛 ...

  4. tomcat session思考

    最近在做统计服务器在线人数时,按照当前服务器session数量来实现,具体方法:实现HttpSessionListener接口来,每次sessionCreate的时候增加1,sessionDestro ...

  5. JS数据类型&&typeof&&其他

    1. 5种基本数据类型: 1. String 2. Number 3. Boolean 4. Undefined 5. Null 2. 1种复杂数据类型:Object 3. 检测变量的数据类型:typ ...

  6. [HDOJ - 5282] Senior's String 【DP】

    题目链接:BZOJ - 5282 题目分析 LCS 就是用经典的 O(n^2) DP 解决,f[i][j] 表示 x 串前 i 个字符与 y 串前 j 个字符的 LCS 长度. f[i][j] = m ...

  7. sqlite优化记录:建立索引加快查询速度

    凡是数据库中,索引的存在就是为了提高查询速度的,数据库的索引有点类似于书本上面的目录的概念,因为在英文中都是index,事实上也就是目录. 其算法应该叫做“倒排索引”,这个其实也类似于搜索引擎里面的基 ...

  8. 几种 Docker 监控工具对比

    轻量级虚拟化容器 Docker,自发布以来便广受业界关注,在开源界和企业界掀起了一阵风.Docker 容器相对于 VM 有以下几个优势:启动速度快:资源利用率高:性能开销小. 从图中可以看出 Dock ...

  9. distinct 去重复查询——两个表join 连接,去掉重复的数据

    ------distinct 去重复查询 select * from  accounts acc join (select distinct accid from roles) r on r.acci ...

  10. POJ 1151 Atlantis(离散化)

    点我看题目 题意 : 就是给你n个矩形的最左下角和最右上角的点的坐标,然后将这n个矩形的面积求出来. 思路 : 离散化求矩形面积并.离散化具体介绍.将横纵坐标离散开来分别存,然后排序,也可以按照黑书上 ...