volcanol的工控博客
Email : lilinly225@126.com 索要资料加QQ 点击进入 或 点击左侧的资料分享专用帖

volcanol ---- View OF Linux Can Appreciate Nature OF Linux

天行健,君子以自强不息

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

      好久没有学习Windows下的编程了, 因为我发现在学习Delphi时;看书的时候一会儿就涉及到windows编程的机制了。

因此在今天有时间的时候学习一下windows的编程。

View Code
#include <windows.h>
//#include "sysmets.h"

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iShowCmd)
{
static TCHAR szAppName[]=TEXT("SysMets4");
static TCHAR szNeedNT[]=TEXT("You need winNT to run this program!");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;

wndclass.cbClsExtra
=0;
wndclass.cbWndExtra
=0;
wndclass.hbrBackground
=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor
=LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon
=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hInstance
=hInstance;
wndclass.lpfnWndProc
=WndProc;
wndclass.lpszClassName
=szAppName;
wndclass.lpszMenuName
=NULL;
wndclass.style
=CS_VREDRAW | CS_HREDRAW;

if(!RegisterClass(&wndclass))
{
MessageBox(NULL,szNeedNT,
"Warning",MB_OK);
return 0;
}

hwnd
=CreateWindow(wndclass.lpszClassName,
szAppName,
WS_OVERLAPPEDWINDOW
|WS_VSCROLL|WS_HSCROLL,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hwnd,iShowCmd);
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)
{
HDC hdc;
PAINTSTRUCT ps;
static int cxChar,
cxCaps,
cyChar,
cxClient,
cyClient,
iMaxWidth;
int i,
x,
y,
iVertPos,
iHorzPos,
iPaintBeg,
iPaintEnd;

SCROLLINFO si;
//通过这个结构体来处理与滚动条相关的消息
/*
结构体的SCROLLINFO
typedef struct tagSCROLLINFO
{
UINT cbSize; //这个字段表示的是结构体变量的大小, 通常设定为cbsize=sizeof SCROLLINFO;
UINT fMask; //调用GetScrollInfo函数和SetScrollPosInfo函数时想要设定的值
int nMin; //V_Range或者R_Range的最小值
int nMax; //滚动范围的最大值
UINT nPage; // 页面的大小, 这个值一般是cyClient/cyChar的大小
int nPos; // 滚动条的当前位置
int nTrackPos; //
} SCROLLINFO, FAR *LPSCROLLINFO;
fMask指定使用结构中哪些成员,不指定的就不使用;可以是以下几个值的任意组合
SIF_ALL
SIF_DISABLENOSCROLL
SIF_PAGE
SIF_POS
SIF_RANGE
SIF_TRACKPOS
函数SetScrollInfo和GetScrollInfo的参数LPSCROLLINFO lpsi指向该结构。在程序中,可以定义如下的SCROLLINFO结构型态:
   SCROLLINFO si ;
  在调用SetScrollInfo或GetScrollInfo之前,必须将cbSize字段设定为结构的大小:
   si.cbSize = sizeof (si) ;
   或
   si.cbSize = sizeof (SCROLLINFO) ;
  
  把fMask字段设定为一个以上以SIF前缀开头的旗标,并且可以使用C的位操作OR运算子(|)组合这些旗标。
  SetScrollInfo函数使用SIF_RANGE旗标时,必须把nMin和nMax字段设定为所需的卷动列范围。
GetScrollInfo函数使用SIF_RANGE旗标时,应把nMin和nMax字段设定为从函数传回的目前范围。
   SIF_POS旗标也一样。当通过SetScrollInfo使用它时,必须把结构的nPos字段设定为所需的位置。
可以通过GetScrollInfo使用SIF_POS旗标来取得目前位置。
  使用SIF_PAGE旗标能够取得页面大小。用SetScrollInfo函数把nPage设定为所需的页面大小。
GetScrollInfo使用SIF_PAGE旗标可以取得目前页面的大小。如果不想得到比例化的卷动列,就不要使用该旗标。
  当处理带有SB_THUMBTRACK或SB_THUMBPOSITION通知码的WM_VSCROLL或WM_HSCROLL消息时,通过GetScrollInfo只使用SIF_TRACKPOS旗标。
从函数的传回中,SCROLLINFO结构的nTrackPos字段将指出目前的32位的卷动方块位置。

*/

//TCHAR szBuffer[10];

TEXTMETRIC tm;

switch(message)
{
case WM_CREATE:
hdc
=GetDC(hwnd);
/*
tm结构体的定义:

*/
GetTextMetrics(hdc,
&tm); //通过这个函数获取设备内容中关于字符系统信息
cxChar=tm.tmAveCharWidth; //表示字符的平均宽度
cyChar=tm.tmHeight+tm.tmExternalLeading; //字符的高度

cxCaps
=(tm.tmPitchAndFamily & 1 ? 3:2)*cxChar /2;
ReleaseDC(hwnd,hdc);

iMaxWidth
=40 * cxChar + 22 * cxCaps;
return 0;
case WM_SIZE:
/*
WM_SIZE消息:
The WM_SIZE message is sent to a window after its size has changed.
当窗口大小发生变化时发送给窗口的消息。
当窗口处理函数接收到WM_SIZE消息时, message会接收一个wm_size消息,而消息的附加消息
会保存在wParam中,其中wParam分为两段:
低字: 保存窗口大小改变后x方向客户区的大小
高字: 保存窗口大小改变后y方向客户区的大小
*/
cxClient
=LOWORD(lParam);
cyClient
=HIWORD(lParam);

si.cbSize
=sizeof si;
//在函数中使用滚动条的滚动范围信息和页面大小信息,这个地方还需要进一步理解
si.fMask=SIF_RANGE | SIF_PAGE;
si.nMin
= 0;
si.nMax
= 100-1;
si.nPage
= cyClient/cyChar;
SetScrollInfo(hwnd,SB_VERT,
&si,TRUE); //SB_VERT:用于窗口中标准垂直滚动条,此处函数仅改变垂直方向的信息

si.cbSize
=sizeof si;
si.fMask
=SIF_RANGE | SIF_PAGE;
si.nMin
= 0;
si.nMax
=2+iMaxWidth+cyChar;
si.nPage
=cxClient/cxChar;
SetScrollInfo(hwnd,SB_HORZ,
&si,TRUE); //SB_HORZ:用于窗口中水平滚动条,此处函数仅改变水平方向滚动条的信息
return 0;
case WM_VSCROLL:
/*
WM_VSCROLL:窗口的垂直滚动条消息。 当接收到这个消息时,wParam参数会附加消息码/通知码。

wParam附加通知码存在该参数的低字, 可以通过LOWORD获取这个通知码消息,并且在一个switch中进行
进行处理。
*/
si.cbSize
=sizeof(si);
si.fMask
=SIF_ALL;
GetScrollInfo(hwnd,SB_VERT,
&si);
iVertPos
=si.nPos;
switch(LOWORD(wParam))
{
case SB_TOP:
si.nPos
=si.nMin;
break;
case SB_BOTTOM:
si.nPos
=si.nMax;
break;
case SB_LINEUP:
si.nPos
+= -1;
break;
case SB_LINEDOWN:
si.nPos
+= 1;
break;
case SB_PAGEUP:
si.nPos
-=si.nPage;
break;
case SB_PAGEDOWN:
si.nPos
=si.nPos+si.nPage;
break;
case SB_THUMBTRACK:
si.nPos
=si.nTrackPos;
break;
default:
break;
}
//Scroll 附加消息处理

si.fMask
=SIF_POS;
SetScrollInfo(hwnd,SB_VERT,
&si,TRUE);
GetScrollInfo(hwnd,SB_VERT,
&si);

if(si.nPos!=iVertPos)
{
ScrollWindow(hwnd,
0,cyChar*(iVertPos-si.nPos),NULL,NULL);
UpdateWindow(hwnd);
}
return 0;
case WM_HSCROLL:
/*
WM_HSCROLL:窗口的水平滚动条消息。 当接收到这个消息时,wParam参数会附加消息码/通知码。

wParam附加通知码存在该参数的低字, 可以通过LOWORD获取这个通知码消息,并且在一个switch中进行
进行处理。
*/
si.cbSize
=sizeof(si);
si.fMask
=SIF_ALL;
GetScrollInfo(hwnd,SB_HORZ,
&si);
iHorzPos
=si.nPos;
switch(LOWORD(wParam))
{
case SB_LINELEFT:
si.nPos
+= -1;
break;
case SB_LINERIGHT:
si.nPos
++;
break;
case SB_PAGELEFT:
si.nPos
-=si.nPage;
break;
case SB_PAGERIGHT:
si.nPos
+=si.nPos;
break;
case SB_THUMBPOSITION:
si.nPos
=si.nTrackPos;
break;
default:
break;
}
// scroll 附加消息处理

si.fMask
=SIF_POS;
SetScrollInfo(hwnd,SB_HORZ,
&si,TRUE);
GetScrollInfo(hwnd,SB_HORZ,
&si);

if(si.nPos != iHorzPos)
{
ScrollWindow(hwnd,cxChar
*(iHorzPos-si.nPos),0,NULL,NULL);
}
return 0;
case WM_KEYDOWN:
/*
WM_KEYDOWN: 窗口的键盘消息
键盘消息分为:
WM_KEYDOWN WM_KEYUP
WM_SYSKEYDOWN WM_SYSKEYUP
这里处理的是非系统键按下消息。
因为键比较多,因此也需要一个消息的附加信息, 这个附加信息还是通过wParam参数进行传递

通常键盘消息的wParam附加信息,成为虚拟键码。 这个参数信息通常用VK_ 开头表示。

在键盘消息里面lParam参数也包含了丰富的信息,这些信息与lParam各个位的取值相关。
*/
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:
SendMessage(hwnd,WM_VSCROLL,SB_PAGEUP,
0);
break;
case VK_NEXT:
SendMessage(hwnd,WM_VSCROLL,SB_PAGEDOWN,
0);
break;
case VK_UP:
SendMessage(hwnd,WM_VSCROLL,SB_LINEUP,
0);
break;
case VK_DOWN:
SendMessage(hwnd,WM_VSCROLL,SB_LINEDOWN,
0);
break;
case VK_LEFT:
SendMessage(hwnd,WM_HSCROLL,SB_LINELEFT,
0);
break;
case VK_RIGHT:
SendMessage(hwnd,WM_HSCROLL,SB_LINERIGHT,
0);
break;
case VK_LWIN:
MessageBox(hwnd,
"You have press left win key!","提示",MB_OK);
break;
}
//keydown 消息处理

case WM_PAINT:
hdc
=BeginPaint(hwnd,&ps);
si.cbSize
=sizeof(si);
si.fMask
=SIF_POS;
GetScrollInfo(hwnd,SB_VERT,
&si);
iVertPos
=si.nPos;

GetScrollInfo(hwnd,SB_HORZ,
&si);
iHorzPos
=si.nPos;

iPaintBeg
=max(0,iVertPos+ps.rcPaint.top/cyChar);
iPaintEnd
=min(1000-1,iVertPos+ps.rcPaint.bottom/cyChar);

for(i=iPaintBeg;i<=iPaintEnd;i++)
{
x
=cxChar* (1-iHorzPos);
y
=cxChar*(1-iVertPos);

TextOut(hdc,x,y,
"abc",strlen("abc"));

TextOut(hdc,x
+22*cxCaps,y,"abcdefg",strlen("abcdefg"));

SetTextAlign(hdc,TA_RIGHT
| TA_TOP);

}
//for 循环
EndPaint(hwnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(
0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);

}

      我发现在目前我学习过的windows编程知识里面,滚动条的处理和字符系统处理比较困难。

      哈哈, 希望自己能够坚持下去, 在2009年的时候,就打算学习win的编程,结果没有坚持下去,

      当时学习的东西又基本忘记了,

       好在目前有博客园,在这里记录学习的点滴,促使我一直坚持学习............

posted on 2011-07-17 23:12  volcanol  阅读(1107)  评论(0编辑  收藏  举报
volcanol ----View OF Linux Can Appreciate Nature OF Linux。