最近学了些关于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. TOKEN+签名验证

    TOKEN+签名验证 首先问大家一个问题,你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或者Get方式请求服务器的时候,会面 ...

  2. MXNet在64位Win7下的编译安装

    注:本文原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) 我笔记本配置比较低,想装个轻量级的MXNet试试,装完之后报错,不是有效的应用程序,找不到 ...

  3. JavaScript: top对象

    一般的JS书里都会在讲框架集的时候讲top,这会让人误解,认为top对象只是代表框架集,其实top的含义应该是说浏览器直接包含的那一个页面对象,也就是说如果你有一个页面被其他页面以iframe的方式包 ...

  4. delphi xe5 android 控制蓝牙

    本文部分内容摘自: http://www.pclviewer.com/android/用以下代码中的接口实现控制蓝牙的开.关及详细信息 unit Androidapi.JNI.BluetoothAda ...

  5. MVC中——Layout和ViewStart以及页面Index之间的关系

    1._ViewStart.cshtml页面是整个MVC中,必定会加载的,它是在一般普通页面,如Index.cshtml页面之前加载. 2._ViewStart.cshtml初始加载页面中,页首一般会包 ...

  6. 1880-A. 偷吃可耻

    描述 EATER买来一堆好吃的,总共N+1份,共(N+1)/2种,每种准备了两份,同种都标上了相同的编号.本来准备与他家吃货一同分享,结果却发现被人偷吃了..EATER发现总数少了一个,所以你的任务就 ...

  7. POJ2201+RMQ

    /* RMQ */ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<algo ...

  8. 服务器部署_linuix下 一台nginx 多域名之二

    第二个需求: 1. 一台服务器部署了三个应用web1~web3对应三个域名:www.web1.com.www.web2.com.www.web3.com ,方法参照我另外一篇文章 2. 如果用非www ...

  9. easyui源码翻译1.32--Calendar(日历)

    前言 前几天加班比较忙 未能及时更新翻译的 今天多发布几篇..下载该插件翻译源码 日历控件显示一个月的日历,允许用户选择日期和移动到下一个或上一个月.默认情况下,一周的第一天是周日.它可以通过设置'f ...

  10. SPRING IN ACTION 第4版笔记-第三章ADVANCING WIRING-007-给BEAN运行时注入值placeholder、@Value

    一.用placeholder给bean运行时注入值的步骤 Spring取得placeholder的值是用${...} 1.声明placeholder bean (1)java方式 In order t ...