標籤:bre setw creat 需要 sdn 通過 ret new http
原文轉自 http://blog.csdn.net/morewindows/article/details/8451638
上一篇《Windows介面編程第三篇 異形表單 普通版》介紹了異形視窗(異形表單)的建立,其主要步驟為——先通過建立位元影像畫刷來做視窗的背景畫刷,再通過SetWindowLong為表單加上WS_EX_LAYERED屬性,然後使用SetLayeredWindowAttributes指定視窗的透明色來完成視窗形狀的調整。並且為了使異形視窗支援滑鼠的拖曳,在WM_LBUTTONDOWN訊息中作了特殊處理。
然後在中有非常相似的兩個異形表單,只不過,左邊的異形表單小,右邊的異形表單大。這個可以怎麼實現了?
先通過其它軟體來縮放位元影像,然後再讓程式載入這種方式來指定異形視窗的大小。這種方法雖然可以完成任務,但畢竟太OUT了。
由《Windows介面編程第一篇位元影像背景與位元影像畫刷》可以想到不用位元影像畫刷,而直接在視窗背景繪製時使用StretchBlt來縮放位元影像至視窗大小,這樣就可以達到指定視窗大小的功能。
由於異形視窗運行後無法通過滑鼠來動態調整視窗大小,因此可以視窗初始化時就可以先縮放位元影像並載入到一個緩衝HDC中,然後再在視窗背景繪製時使用BitBlt來貼圖。這種做法只需要縮放位元影像一次,在每次背景繪製時只須拷貝位元影像,對程式的效率會有提高。下面給出完整原始碼(:http://download.csdn.net/download/morewindows/4966819)
// 異形視窗2 在WM_ERASEBKGND訊息中自貼圖//By MoreWindows-(http://blog.csdn.net/MoreWindows)#include <windows.h>const char szAppName[] = "異形視窗2 MoreWindows-(http://blog.csdn.net/MoreWindows)";/* * 函數名稱: GetWindowSize * 函數功能: 得到視窗的寬高 * hwnd 視窗控制代碼 * pnWidth 視窗寬 * pnHeight 視窗高*/void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight);/* * 函數名稱: InitBitmapWindow * 函數功能: 位元影像視窗初始化 * hinstance 進程執行個體 * nWidth 視窗寬 * nHeight 視窗高 * nCmdshow 顯示方式-與ShowWindow函數的第二個參數相同*/BOOL InitBitmapWindow(HINSTANCE hinstance, int nWidth, int nHeight, int nCmdshow);// 位元影像視窗訊息處理函數LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm); HBITMAP g_hBitmap;int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ //先建立一個無背影畫刷視窗, //然後在WM_CREATE中並指定透明顏色, 縮放位元影像後載入至s_hdcMem中. //最後在WM_ERASEBKGND中用s_hdcMem貼圖即可 g_hBitmap = (HBITMAP)LoadImage(NULL, "Kitty.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); if (g_hBitmap == NULL) { MessageBox(NULL, "位元影像載入失敗", "Error", MB_ICONERROR); return 0; } // 設定異形視窗大小 BITMAP bm; GetObject(g_hBitmap, sizeof(bm), &bm); int nWindowWidth = bm.bmWidth; int nWindowHeight = bm.bmHeight + 100; //拉高100高度 if (!InitBitmapWindow(hInstance, nWindowWidth, nWindowHeight, nCmdShow)) return 0; MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } DeleteObject(g_hBitmap); return msg.wParam;}BOOL InitBitmapWindow(HINSTANCE hinstance, int nWidth, int nHeight, int nCmdshow){ HWND hwnd; WNDCLASS wndclass; wndclass.style = CS_VREDRAW | CS_HREDRAW; wndclass.lpfnWndProc = BitmapWindowWndPrco; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hinstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);//視窗背影畫刷為空白 wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, "Program Need Windows NT!", "Error", MB_ICONERROR); return FALSE; } hwnd = CreateWindowEx(WS_EX_TOPMOST, szAppName, szAppName, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, nWidth, nHeight, NULL, NULL, hinstance, NULL); if (hwnd == NULL) return FALSE; ShowWindow(hwnd, nCmdshow); UpdateWindow(hwnd); return TRUE;}LRESULT CALLBACK BitmapWindowWndPrco(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParm){ static HDC s_hdcMem; //放置縮放後的位元影像 switch (message) { case WM_CREATE: { // 設定分層屬性 SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); // 設定透明色 COLORREF clTransparent = RGB(0, 0, 0); SetLayeredWindowAttributes(hwnd, clTransparent, 0, LWA_COLORKEY); // 縮放位元影像 // 載入位元影像到hdcTemp中 HDC hdc = GetDC(hwnd); HDC hdcTemp = CreateCompatibleDC(hdc); SelectObject(hdcTemp, g_hBitmap); // 得到視窗大小 int nWidth, nHeight; GetWindowSize(hwnd, &nWidth, &nHeight); // 建立與視窗大小相等且能容納位元影像的HDC - s_hdcMem s_hdcMem = CreateCompatibleDC(hdc); HBITMAP hbmp = CreateCompatibleBitmap(hdc, nWidth, nHeight); SelectObject(s_hdcMem, hbmp); // 將原位元影像縮放到視窗大小 BITMAP bm; GetObject(g_hBitmap, sizeof(bm), &bm); StretchBlt(s_hdcMem, 0, 0, nWidth, nHeight, hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); // 釋放資源 DeleteDC(hdcTemp); ReleaseDC(hwnd, hdc); } return 0; case WM_KEYDOWN: switch (wParam) { case VK_ESCAPE: //按下Esc鍵時退出 SendMessage(hwnd, WM_DESTROY, 0, 0); return TRUE; } break; case WM_LBUTTONDOWN: //當滑鼠左鍵點擊時可以拖曳視窗 PostMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0); return TRUE; case WM_ERASEBKGND: //在視窗背景中直接貼圖 { HDC hdc = (HDC)wParam; int nWidth, nHeight; GetWindowSize(hwnd, &nWidth, &nHeight); BitBlt(hdc, 0, 0, nWidth, nHeight, s_hdcMem, 0, 0, SRCCOPY); return TRUE; } case WM_DESTROY: DeleteDC(s_hdcMem); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParm);}void GetWindowSize(HWND hwnd, int *pnWidth, int *pnHeight){ RECT rc; GetWindowRect(hwnd, &rc); *pnWidth = rc.right - rc.left; *pnHeight = rc.bottom - rc.top;}
運行程式將得到如文章中每一張圖右邊所示的異形視窗。最後總結一下異形視窗的“三要素”:
1.WS_EX_LAYERED屬性
2.以位元影像為視窗背景(自貼圖或位元影像畫刷)
3.指定透明色
本文配套程式為:http://download.csdn.net/download/morewindows/4966819
當視窗的背景用彩色圖片來裝飾時,其它控制項如果還是用灰色的背景會顯的比較不諧調,《Windows介面編程第五篇 靜態控制項背景透明化》將介紹如何為靜態框設定透明背景。
Windows介面編程第四篇 異形表單(轉)