//这是我初次编写windows应用程序(窗口),按理说是按书本上的抄录下来的,呵呵
//下面我把代码详细解释一下
/**********************一些字符前缀解释****************************************************/
/*cs_:class(类风格选项),WM_:widows message(窗口消息),CW_:creat widows(绘制窗口)
DT_:draw text(绘制文本选项)
RECT:rectangle(巨型),instance:实例 h:handle(句柄,行为,把手) vertical:垂直
horizontal:水平的
*/
//此程序中在窗口中添加了滚动条内容
#include <windows.h>
#include "SYSMETS.h"
LRESULT CALLBACK WndProc(
HWND hwnd, // handle to window
UINT Msg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int iCmdShow // show state
)
{
static TCHAR szAppName[]=TEXT("SysMets");
MSG msg; //定义一个消息结构
WNDCLASS wndclass;
//下面的一部分相当于设计,先初始化了窗口类的共有属性
wndclass.style=CS_HREDRAW |CS_VREDRAW; //
wndclass.lpfnWndProc=WndProc; //指向所有基于这个类来创建的窗口所使用的窗口过程的地址
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_ERROR); //窗口左上角是一个叉的图标
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW); //光标选项(也就是鼠标)
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //客户区背景
wndclass.lpszMenuName=NULL; //在vc中,有菜单,这个程序,没有菜单,所以为NULL
wndclass.lpszClassName=szAppName; //这个类的名字
if(!RegisterClass(&wndclass)) //注册窗口类
{
MessageBox(NULL,TEXT("This program requires Windows NT!"),
szAppName,MB_ICONERROR);
return 0;
}
HWND hwnd; //定义一个窗口句柄,开始创建窗口
hwnd=CreateWindow( //创建窗口
szAppName, // registered class name
TEXT("The Hello Program"), // window name
/*********************WS_OVERLAPPEDWINDOW 重叠式窗口****************************************************/
//创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU,WS_THICKFRAME,WS_MINIMIZEBOX和WS_MAXIMIZEBOX
/*WS_OVERLAPPEDWINDOW*/WS_MINIMIZEBOX|WS_OVERLAPPED|WS_SYSMENU|WS_THICKFRAME|WS_MAXIMIZEBOX|WS_VSCROLL|WS_HSCROLL,//增加垂直滚动条和水平滚动条
CW_USEDEFAULT, // horizontal position of window
CW_USEDEFAULT, // vertical position of window
CW_USEDEFAULT, // window width
CW_USEDEFAULT, // window height
NULL, // handle to parent or owner window
NULL, // menu handle or child identifier
hInstance, // handle to application instance
NULL // window-creation data
);
ShowWindow(hwnd,iCmdShow); //显示窗口
UpdateWindow(hwnd); //更新窗口
while(GetMessage(&msg,NULL,0,0)) //消息循环(这一步是从消息队列中得到消息)
{
TranslateMessage(&msg); //消息转换
DispatchMessage(&msg); //消息映射(如果在MFC中,这是一个非常难的难点)
}
return msg.lParam; //如果得到一个WM_QUIT消息,退出while()循环,程序返回结束
}
//窗口过程函数
LRESULT CALLBACK WndProc(
HWND hwnd, // handle to window
UINT msg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
static int cxChar,cxCaps,cyChar,cyClient,iVscrollPos;
int i,y;
TCHAR szBuffer[10];
TEXTMETRIC tm;
HDC hdc;
PAINTSTRUCT ps;
// RECT rect;
switch(msg)
{
case WM_CREATE: //创建窗口时由windows发送给窗口过程的,此时消息并没有进入消息队列
// PlaySound(TEXT("hello,war"),NULL,SND_FILENAME|SND_ASYNC);
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);
// SetScrollRange(hwnd,SB_VERT,0,NUMLINES-1,FALSE); //设置垂直滚动条的范围(自我感觉一下两句没有用处)
// SetScrollPos(hwnd,SB_VERT,iVscrollPos,TRUE); //设置垂直滚动条的位置
return 0;
case WM_SIZE: //窗口大小改变时,产生的消息(当然,窗口第一次显示时,也是要产生这个消息的,接下来必然跟着WM_PAINT消息)
cyClient=HIWORD(lParam); //lParam 低字节用于客户区的垂直大小
break;
case WM_VSCROLL: //滚动条消息
switch(LOWORD(wParam))//wParam的低字节指出了鼠标对滚动条进行的操作
{
case SB_LINEUP:
iVscrollPos-=1;
break;
case SB_LINEDOWN:
iVscrollPos+=1;
break;
case SB_PAGEUP:
iVscrollPos-=cyClient/cyChar;
break;
case SB_PAGEDOWN:
iVscrollPos+=cyClient/cyChar;
break;
case SB_THUMBTRACK/*SB_THUMBPOSITION*/: //释放滚动条/按下滚动条
iVscrollPos=HIWORD(wParam); //高字节附加参数,此时指出位置变化为释放后的/按下滚动条
break;
default:
break;
}
iVscrollPos=max(0,min(iVscrollPos,NUMLINES-1)); //使滚动条为位置不至于超出范围
if(iVscrollPos !=GetScrollPos(hwnd,SB_VERT))
{
SetScrollPos(hwnd,SB_VERT,iVscrollPos,TRUE); //重新设置滚动条位置
InvalidateRect(hwnd,NULL,TRUE); //是客户区无效
// UpdateWindow(hwnd);
}
return 0;
case WM_PAINT: //此消息也不是从消息队列中获得的,也是widows发送的
hdc=BeginPaint(hwnd,&ps); //返回的是一个“设备描述表句柄”
for(i=0;i<NUMLINES;i++)
{
y=cyChar*(i-iVscrollPos);
//y=cyChar*i;
TextOut(hdc,0,y,sysmetrics[i].szLabel,lstrlen(sysmetrics[i].szLabel)); //显示第一列
TextOut(hdc,22*cxChar,y,sysmetrics[i].szDesc,lstrlen(sysmetrics[i].szLabel)); //显示第一列
SetTextAlign(hdc,TA_RIGHT|TA_TOP); //设置为对齐方式(右上对齐)
TextOut(hdc,22*cxChar+40*cxChar,y,szBuffer,wsprintf(szBuffer,TEXT("%5d"),GetSystemMetrics(sysmetrics[i].ilndex)));//显示第三列
SetTextAlign(hdc,TA_LEFT|TA_TOP); //设置为对齐方式(重新设置为普通方式对齐)
}
/* GetClientRect(hwnd,&rect); //通过这个函数可以获得变化后的窗口大小(我也不知道怎么实现的)
DrawText(
hdc, // handle to DC
TEXT("Hello,Windows xp!"), // text to draw
-1, // text length
&rect, // formatting dimensions
DT_SINGLELINE|DT_CENTER|DT_VCENTER // text-drawing options
);*/
EndPaint(hwnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
/*分析WM_PAINT消息:如果用户最终单击了关闭按钮,DefWindowProc处理键盘和鼠标输入,检测到close选项后,
给窗口过程发送一个WM_SYSCOMMAND消息,WndProc将这个消息传给DefWindowProc,此函数给窗口过程发送一个WM_CLOSE消息
来响应之,DestroyWindow 导致Windows给窗口过程发送一个WM_DESTROY消息。WndProc再调用PostQuitMessage,将一个
WM_QUIT
消息放入消息队列中,以此来响应此消息,这个消息导致WinMain中的消息循环终止,循环结束。*/
//消息分为进队消息和不进队消息,从上面可以看出,在窗口没有创建以前,WM_CREATE和WM_PAINT
//都是不进队列的,直接由windows发送,不管我们的事