windows程式設計(3):分解掃雷程式之雷區翻蓋

來源:互聯網
上載者:User

假如讓你寫一個掃雷程式,在沒有相關資料的前提下,應該從哪裡入手呢?

我們先想想掃雷程式都有什麼:菜單,秒錶,記雷數,複位,還有雷區等雜七雜八的東西。而整個程式的關鍵,就在於雷區。因為如果沒有秒錶,記雷數等功能,掃雷勉強還是可以玩的,但如果沒了雷區,就玩不了了。那麼雷區又是怎麼一回事呢?肯定要有一個資料結構來記錄地雷和周圍的數,而程式跟你互動的主要部分,就是在雷區上點一下,然後顯示一幅圖片,還有雙擊雷區翻開周圍一片的操作。說白了,就是在畫圖。所以整個掃雷程式,就從畫圖先開始吧。

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){static HBITMAP hBitmap;static int cxClient,cyClient,cxSource,cySource;//位元影像類結構,包含位元影像的資訊BITMAP bitmap;//裝置內容控制代碼HDC hdc,hdcMem;//這條訊息的執行個體控制代碼,因為只在WM_CREATE訊息中獲得,所以是建立的視窗的執行個體控制代碼HINSTANCE hInstance;int x,y,mx,my;//PAINTSTRUCT結構包含了繪製用戶端區域的資訊,第一個參數就是HDC類的PAINTSTRUCT ps;//控制距離的變數int dstx = 100;int dsty = 100;switch(message){//建立視窗訊息:第一個訊息case WM_CREATE://LPCREATESTRUCT是一個指向結構CREATESTRUCT的指標//對lParam強制類型轉換以後指向結構體,結構體中的hInstancehInstance = ((LPCREATESTRUCT)lParam)->hInstance;//裝載位元影像:參數為執行個體控制代碼,位元影像,傳回值為位元影像控制代碼//雖然也可以使用位元影像名稱來裝載位元影像,但是通常都是用序號hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE  (IDB_BITMAP2));//從指定的繪圖物件中擷取資訊//參數為:圖形控制代碼,對象資訊緩衝區的大小,對象資訊緩衝區GetObject(hBitmap,sizeof(BITMAP),&bitmap);//一幅位元影像的寬cxSource = bitmap.bmWidth;//一幅位元影像的高:整個位元影像由16種不同的圖形組成,每幅圖形應為整個位元影像的16分之1cySource = bitmap.bmHeight/16;return 0;//改變視窗大小訊息case WM_SIZE://32位值的高低位代表客戶區的長寬//不同的訊息間需要保留,所以用的是staticcxClient = LOWORD(lParam);cyClient = HIWORD(lParam);return 0;//繪製視窗訊息case WM_PAINT://BeginPaint函數準備畫圖,向PAINTSTRUCT結構中填充資訊//參數為:視窗控制代碼、指向PAINTSTRUCT結構的畫圖資訊,傳回值為一個HDChdc = BeginPaint (hwnd, &ps) ;//建立記憶體的裝置環境,傳回值是一個記憶體裝置環境的控制代碼hdcMem = CreateCompatibleDC(hdc);//將一個對象選擇到裝置環境中,參數為:裝置環境控制代碼,物件控點SelectObject(hdcMem,hBitmap);for(y = dsty; y < cyClient-dsty;y += cySource){for(x = dstx; x < cxClient-dstx;x += cxSource){//貼圖函數,參數為:目標DC控制代碼,貼圖點的左上方的x座標,貼圖點的左上方的y座標,目標和源的長,目標和圓的寬,源DC控制代碼,源的左上方x座標,源的左上方y座標,光柵作業碼(這裡是直接從源矩形複製到目標矩形)BitBlt(hdc,x,y,cxSource,cySource,hdcMem,0,0,SRCCOPY);}}DeleteDC(hdcMem);//繪製視窗結束EndPaint (hwnd, &ps) ; return 0;

注意到,使用WM_SIZE訊息擷取了客戶區的大小。在WM_PAINT訊息的二重迴圈中,通過它來改變貼多少方磚。

那麼如何?滑鼠點一下就翻開呢?

case WM_LBUTTONDOWN://左鍵會顯示雷區被翻開的效果hdc = GetDC(hwnd);hdcMem =  CreateCompatibleDC(hdc);SelectObject(hdcMem,hBitmap); //使得滑鼠點到哪裡,就選擇那裡的雷區,並畫一幅翻開的圖片//滑鼠點到雷區外,不起作用//滑鼠點到雷區裡,用這個方塊的左上方代替貼圖的位置//滑鼠的位置: mx = (LOWORD(lParam)); my = (HIWORD(lParam)); //點到雷區裡面才有效,雷區的位置:離上下dsty,左右dstx if(mx>dstx && mx<cxClient-dstx && my>dsty && my<cyClient-dsty) {//將滑鼠的位置改為這個點的對應的雷區的方磚的左上方//結果總是在第一塊磚上mx = ((int)(mx-dstx)/cxSource)*cxSource+dstx;my = ((int)(my-dsty)/cySource)*cySource+dsty;//貼圖函數,參數為:目標DC控制代碼,貼圖點左上方的x座標,貼圖點左上方的y座標,目標矩形的長,目標矩形的寬,源DC控制代碼,源的左上方x座標,源的左上方y座標,光柵作業碼(這裡是直接從源矩形複製到目標矩形)BitBlt(hdc,mx,my,cxSource,cySource,hdcMem,0,cySource*15,SRCCOPY);  } DeleteDC(hdcMem);ReleaseDC(hwnd,hdc);return 0;
 //關閉視窗訊息 case WM_DESTROY:  PostQuitMessage (0) ;  return 0;  } return DefWindowProc (hwnd, message, wParam, lParam) ; //執行預設訊息}

就是滑鼠點一下,將滑鼠點的位置換成它屬於的方磚的位置,然後貼上另一種方磚即可。位置的轉化原理其實很簡單,就是利用C語言中int類型資料整除的性質,舉個例子:

如果一塊方磚的大小為16*16,你滑鼠的位置為(30,50),那麼它所屬的方磚的左上方,肯定是在30/16 =1, 50/16 = 3就是第一列,第三行的那裡,具體的像素就是(1*16,3*16)。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.