windows繪圖

 

Tetris Windows API代碼記錄:windows

1. 下面是Windows API代碼框架,感受用API寫東西比別的框架清爽不少。數組

 

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); //窗口過程函數
/*

     程序的入口點WinMain函數
     第一個參數:應用程序的當前實例句柄。
     第二個參數:應用程序的前一個實例句柄,別管它,對於Win32位而言,它通常是NULL.

     第三個參數:指向任何傳給程序的命令行參數。PSTR表明"指向字符串的指針"。
     第四個參數:它告訴應用程序如何初始化窗口,如最大化,最小化等狀態。
     WinMain()所起的做用:初始化,展現,銷燬應用程序等。
*/

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)

{

     static TCHAR szAppName[] = TEXT("Hello Win");

     HWND hwnd;//定義窗口句柄
     MSG msg;//建立消息
     WNDCLASS wc;//定義窗口類,下面是窗口類的結構定義
     
	 /*
     typedef struct _WNDCLASSA 
   { 
     UINT style ;         //窗口類風格
     WNDPROC lpfnWndProc ;    //指向窗口過程函數的指針
     int cbClsExtra ;       //窗口類附加數據
     int cbWndExtra ;      //窗口附加數據
     HINSTANCE hInstance ;    //擁有窗口類的實例句柄
     HICON hIcon ;        //最小窗口圖標
     HCURSOR hCursor ;      //窗口內使用的光標
     HBRUSH hbrBackground ;   //用來着色窗口背景的刷子
     LPCSTR lpszMenuName ;   //指向菜單資源名的指針
     LPCSTR lpszClassName ;   // 指向窗口類名的指針
   } 
     */

 

     wc.style = CS_HREDRAW | CS_VREDRAW; //窗口類風格
     wc.lpfnWndProc = WndProc; //指向窗口過程函數的指針
     wc.cbWndExtra = 0; //窗口類附加數據
     wc.cbClsExtra = 0; //窗口附加數據
     wc.hInstance = hinstance; //擁有窗口類的實例句柄
     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); //最小窗口圖標
     wc.hCursor = LoadCursor(NULL, IDC_HAND);//窗口內使用的光標
     wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); //用來着色窗口背景的刷子
     wc.lpszMenuName = NULL;//指向菜單資源名的指針
     wc.lpszClassName = szAppName;// 指向窗口類名的指針
 

     //註冊窗口類
     if (!RegisterClass(&wc))
     {
         MessageBox(NULL, TEXT("This program requires Windows NT"),szAppName,MB_ICONERROR);
         return 0;
     }

     //建立窗口,下面是函數原型
     /*
     HWND CreateWindow( LPCTSTR lpClassName,
						LPCTSTR lpWindowName,
						DWORD dwStyle,
						int x,
						int y,
						int nWidth,
						int nHeight,
						HWND hWndParent,
						HMENU hMenu,
						HINSTANCE hInstance,
						LPVOID lpParam
					);

 

     參數1:登記的窗口類名,這個類名剛纔我們在註冊窗口時已經定義過了。
     參數2:用來代表窗口的標題。
     參數3: 用來代表窗口的風格,若有無最大化,最小化按紐啊什麼的。
     參數4,5: 用來代表程序運行後窗口在屏幕中的座標值。
     參數6,7: 用來代表窗口初始化時(即程序初運行時)窗口的大小,即長度與寬度。
     參數8: 在建立窗口時能夠指定其父窗口,這裏沒有父窗口則參數值爲。
     參數9: 用以指明窗口的菜單,菜單之後會講,這裏暫時爲。
     最後一個參數是附加數據,通常都是NULL。
     CreateWindow()的返回值是已經建立的窗口的句柄,應用程序使用這個句柄來引用該窗口。若是返回值爲,就應該終止該程序,
     由於可能某個地方出錯了。若是一個程序建立了多個窗口,則每一個窗口都有各自不一樣的句柄.
     */

     hwnd = CreateWindow(szAppName,TEXT("Welcome to Windows API!"), WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
						CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL, NULL, hinstance,NULL);

     /*顯示窗口
 
     其第一個參數是窗口句柄,告訴ShowWindow()顯示哪個窗口,而第二個參數則告訴它如何顯示這個窗口:
     最小化(SW_MINIMIZE),普通(SW_SHOWNORMAL),仍是最大化(SW_SHOWMAXIMIZED)。WinMain在建立完窗口後就調用ShowWindow函數,
     並把nCmdShow參數傳送給這個窗口。
     */

     ShowWindow(hwnd, nCmdShow);

 

     //更新窗口
     UpdateWindow(hwnd);

 

     //消息循環
     /*

     GetMessage(&msg,NULL,0,0),第一個參數是要接收消息的MSG結構的地址,第二個參數表示窗口句柄,

     NULL則表示要獲取該應用程序建立的全部窗口的消息;第三,四參數指定消息範圍。後面三個參數被設置爲默認值,
     這就是說你打算接收發送到屬於這個應用程序的任何一個窗口的全部消息。在接收到除WM_QUIT以外的任何一個消息後,
     GetMessage()都返回TRUE。若是GetMessage收到一個WM_QUIT消息,則返回FALSE,如收到其餘消息,則返回TRUE。所以,
     在接收到WM_QUIT以前,帶有GetMessage()的消息循環能夠一直循環下去。只有當收到的消息是WM_QUIT時,GetMessage才
     返回FALSE,結束消息循環,從而終止應用程序。均爲NULL時就表示獲取全部消息。
     */

     while (GetMessage(&msg,NULL, 0, 0))
     {
         TranslateMessage(&msg);//翻譯消息
         DispatchMessage(&msg);//撤去消息
     }

     return msg.wParam;
}

 

//窗口過程函數
LRESULT CALLBACK WndProc(HWND hwnd,    //Handle to the window
                         UINT message, // Specifies the message
						 WPARAM wParam,//Specifies additional message information
						 LPARAM lParam)// Specifies additional message information

{

     HDC hdc;//Handle the device context
     PAINTSTRUCT ps;
     RECT rect;

     //消息處理
     switch (message)
     {
     case WM_PAINT://重繪消息
         hdc = BeginPaint(hwnd, &ps);
         GetClientRect(hwnd, &rect);
         DrawText(hdc, TEXT("Hello, Windows API!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
         EndPaint(hwnd, &ps);
         return 0;

     case WM_DESTROY://窗口銷燬消息
         PostQuitMessage(0);
         return 0;

     default://其餘消息由這個默認處理函數來處理
         return DefWindowProc(hwnd, message, wParam,lParam);
     }
}

 

2. 類中的數組不能直接={}賦值;則採用以下技巧:框架

 

class A{
        private :
                  int m_arr[10];
       public:
             A()
            {
                   int temp_arr[10] = {1,2,3,4,5,6,7,8,9,10};
                   memcpy(m_arr,temp_arr,sizeof(temp_arr));
             }
 
      ....................
 }

 

3. 類中的const int不能開數組。可是static const int 能夠。好比函數

private:
	//data
	static const int _mapheight = 23;
	static const int _mapwidth = 13;
	static const int _nblocktype = 7;
	int _tmap[_mapheight][_mapwidth]; //covered = 1; uncovered = 0;

 

 

 

 

4. 在case語句下若是有聲明變量要加{}ui

5. 使用windows API繪圖時很容易產生閃屏現象,須要使用雙緩衝機制。特別注意釋放內存。代碼參照: RECT中的bottom>top;spa

			HDC hMemDC;
			HBITMAP hbmp;



			hMemDC = CreateCompatibleDC(hdc); 
			hbmp = CreateCompatibleBitmap(hdc, rect.right-rect.left,  rect.bottom - rect.top );
			SelectObject(hMemDC, hbmp);
			HBRUSH hb = CreateSolidBrush(RGB(0, 0, 0));
			FillRect(hMemDC, &rect, CreateSolidBrush(GetBkColor(hdc)));  
			
			//printf parameters
			RECT outputrect; outputrect.left = 10;
			outputrect.right = 300; outputrect.top = 10; outputrect.bottom = 30;
			char debug[20];sprintf(debug,"state: %d", myTetris._state);
			DrawText(hMemDC, debug, -1, &outputrect, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
			
			outputrect.top += 20; outputrect.bottom += 20;
			sprintf(debug,"blockstate: %d", myTetris._blockstate);
			DrawText(hMemDC, debug, -1, &outputrect, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
			
			outputrect.top += 20; outputrect.bottom += 20;
			sprintf(debug,"block_y: %d", myTetris._block_y);
			DrawText(hMemDC, debug, -1, &outputrect, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
						
			outputrect.top += 20; outputrect.bottom += 20;
			sprintf(debug,"block_x: %d", myTetris._block_x);
			DrawText(hMemDC, debug, -1, &outputrect, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
			
			int map[23][13];
			myTetris.getMap(map);

			MoveToEx(hMemDC, rect.right/2 - 6.5*20 , rect.bottom - 0 ,NULL);
			LineTo(hMemDC,  rect.right/2 - 6.5*20 , rect.bottom - 23*20);

			MoveToEx(hMemDC, rect.right/2 - 6.5*20 , rect.bottom - 0 ,NULL);
			LineTo(hMemDC,  rect.right/2 + 6.5*20 , rect.bottom - 0);

			MoveToEx(hMemDC, rect.right/2 + 6.5*20 , rect.bottom - 0 ,NULL);
			LineTo(hMemDC,  rect.right/2 + 6.5*20 , rect.bottom - 23*20);

			MoveToEx(hMemDC, rect.right/2 - 6.5*20 , rect.bottom - 23*20 ,NULL);
			LineTo(hMemDC,  rect.right/2 + 6.5*20 , rect.bottom - 23*20);

			for(int i = 0 ; i < 23; i++)
			{
				for(int j = 0 ; j < 13; j++)
				{
					if(map[i][j])
					{
						RECT* prect = new RECT();
						prect->bottom = rect.bottom - i*20;
						prect->left = j*20 + rect.right/2 - 6.5*20;
						prect->top = prect->bottom - 18;
						prect->right = prect->left + 18;
						
						FillRect(hMemDC, prect, hb);
						
					}
				}
			}

			BitBlt(hdc,0,0,rect.right-rect.left,rect.bottom - rect.top,hMemDC,0,0,SRCCOPY); 

			DeleteObject(hbmp);
			DeleteObject(hMemDC);
			DeleteObject(hb);
			ReleaseDC(hwnd,hdc);

			EndPaint(hwnd, &ps);


注意響應WM_ERASEBKGND消息命令行

相關文章
相關標籤/搜索