windows绘图

 

Tetris Windows API代码记录:

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语句下如果有声明变量要加{}

5. 使用windows API绘图时很容易产生闪屏现象,需要使用双缓冲机制。特别注意释放内存。代码参照: RECT中的bottom>top;

			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消息


posted @ 2013-06-18 22:54  little_hsu  阅读(249)  评论(0编辑  收藏  举报