Windows滾動條

//這是我初次編寫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_MINIMIZEBOXWS_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_CREATEWM_PAINT

//都是不進隊列的,直接由windows發送,不管我們的事

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章