//這是我初次編寫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發送,不管我們的事