1. 为Sysmets3程序添加击键消息:
1) 主要是添加了Page Up、Page Down、光标方向键等击键消息,用于页面翻滚;
2) 我们没有必要在每个击键消息中添加滚条操作的代码,而只要在WM_KEYDOWN消息中使用SendMessage函数传递假的WM_SCROLL消息给窗口来模拟滚条消息即可,这样就可以让滚条消息响应只处理滚条消息,这样分工明确,不会让代码冗余杂乱;
3) 关于SendMessage函数的用法:
SendMessage( hWnd, message, wParam, lParam );
直接将一条消息按照参数指定的那样包装成MSG结构体发送给响应的窗口hWnd处,hWnd可以不是产生该消息的窗口,可以是该程序的其它窗口甚至是其它程序的窗口(程序间的通信);
在这里这需要这样使用即可:
case WM_KEYDOWN:
switch ( wParam )
{
case VK_HOME:
SendMessage( hWnd, WM_VSCROLL, SB_TOP, 0 );
break;
....
}
...
4) 具体代码:
// sysmets4.c
#include <windows.h>
#include "sysmets.h"
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPreInstanc,
LPSTR lpszCmdLine,
int nCmdShow
)
{
static TCHAR szAppName[] = TEXT("sysmets4");
WNDCLASS wndclass;
HWND hWnd;
MSG msg;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
RegisterClass( &wndclass );
hWnd = CreateWindow(
szAppName, TEXT("Get System Metrics Version 4"),
WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL
);
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
while ( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
return msg.wParam;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
static int cxChar, cxCaps, cyChar;
static int cxClient, cyClient;
static int nMaxWidth, nMaxHeight;
TCHAR szBuffer[10];
HDC hdc;
PAINTSTRUCT ps;
TEXTMETRIC tm;
SCROLLINFO si;
int iPreVertPos, iPreHorzPos;
int iCurVertPos, iCurHorzPos;
int iBeginPaint, iEndPaint;
int i;
int x, y;
switch ( message )
{
case WM_CREATE:
hdc = GetDC( hWnd );
GetTextMetrics( hdc, &tm );
cxChar = tm.tmAveCharWidth;
cxCaps = ( tm.tmPitchAndFamily & 1 ? 3 : 2 ) * cxChar / 2;
cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC( hWnd, hdc );
nMaxWidth = 2 + ( 22 * cxCaps + 40 * cxChar ) / cxChar;
nMaxHeight = NUMLINES - 1;
return 0;
case WM_SIZE:
cxClient = LOWORD( lParam );
cyClient = HIWORD( lParam );
si.cbSize = sizeof( SCROLLINFO );
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = nMaxHeight;
si.nPage = cyClient / cyChar;
SetScrollInfo( hWnd, SB_VERT, &si, TRUE );
si.cbSize = sizeof( SCROLLINFO );
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = nMaxWidth;
si.nPage = cxClient / cxChar;
SetScrollInfo( hWnd, SB_HORZ, &si, TRUE );
return 0;
case WM_VSCROLL:
si.fMask = SIF_ALL;
GetScrollInfo( hWnd, SB_VERT, &si );
iPreVertPos = si.nPos;
switch ( LOWORD( wParam ) )
{
case SB_TOP: // 在滚条上直接用鼠标操作并不会产生这样的消息
// 这样的消息只有通过WM_KEYDOWN中通过SendMessage产生
si.nPos = si.nMin;
break;
case SB_BOTTOM:
si.nPos = si.nMax;
break;
case SB_LINEUP:
si.nPos--;
break;
case SB_LINEDOWN:
si.nPos++;
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
}
si.cbSize = sizeof( SCROLLINFO );
si.fMask = SIF_POS;
SetScrollInfo( hWnd, SB_VERT, &si, TRUE );
GetScrollInfo( hWnd, SB_VERT, &si );
if ( si.nPos != iPreVertPos )
{
ScrollWindow( hWnd, 0, cyChar * ( iPreVertPos - si.nPos ), NULL, NULL );
}
return 0;
case WM_HSCROLL:
si.fMask = SIF_ALL;
GetScrollInfo( hWnd, SB_HORZ, &si );
iPreHorzPos = si.nPos;
switch ( LOWORD( wParam ) )
{
case SB_LEFT:
si.nPos = si.nMin;
break;
case SB_RIGHT:
si.nPos = si.nMax;
break;
case SB_LINELEFT:
si.nPos--;
break;
case SB_LINERIGHT:
si.nPos++;
break;
case SB_PAGELEFT:
si.nPos -= si.nPage;
break;
case SB_PAGERIGHT:
si.nPos += si.nPage;
break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
}
si.cbSize = sizeof( SCROLLINFO );
si.fMask = SIF_POS;
SetScrollInfo( hWnd, SB_HORZ, &si, TRUE );
GetScrollInfo( hWnd, SB_HORZ, &si );
if ( si.nPos != iPreHorzPos )
{
ScrollWindow( hWnd, cxChar * ( iPreHorzPos - si.nPos ), 0, NULL, NULL );
}
return 0;
case WM_KEYDOWN:
switch ( wParam )
{
case VK_HOME: // 顶部
SendMessage( hWnd, WM_VSCROLL, SB_TOP, 0 );
break;
case VK_END: // 底部
SendMessage( hWnd, WM_VSCROLL, SB_BOTTOM, 0 );
break;
case VK_PRIOR: // 上一页,Page Up
SendMessage( hWnd, WM_VSCROLL, SB_PAGEUP, 0 );
break;
case VK_NEXT: // 下一页,P