1. 程式人生 > >Windows核心程式設計_異型視窗(續)

Windows核心程式設計_異型視窗(續)

上一篇文章介紹的是使用SetLayeredWindowAttributes

API來實現異型視窗,但是很明顯效果很差勁,在剔除顏色的過程中凹凸邊緣區域的畫素點會剔除的非常不明顯,在查詢資訊之後,得出的說法是當顯示屏在顯示影象的時候在顏色重疊的地方會產生顏色色差,而SetLayeredWindowAttributes 又是從螢幕中取出dc顏色的!

但這次我們使用UpdateLayeredWindow方法來將PNG影象直接載入到視窗上!

思路:

使用gdi載入png圖片,然後使用UpdateLayeredWindow載入到視窗上!

分層視窗的概念可以參考我的上一篇文章裡的介紹!

這裡先看一下執行效果:

API介紹:

UpdateLayeredWindow

函式原型:

BOOL WINAPI UpdateLayeredWindow(
  _In_     HWND          hwnd,
  _In_opt_ HDC           hdcDst,
  _In_opt_ POINT         *pptDst,
  _In_opt_ SIZE          *psize,
  _In_opt_ HDC           hdcSrc,
  _In_opt_ POINT         *pptSrc,
  _In_     COLORREF      crKey,
  _In_opt_ BLENDFUNCTION *pblend,
  _In_     DWORD         dwFlags
);

引數介紹:

引數

型別

說明

hwnd

HWND

一個分層視窗的控制代碼。分層視窗在用CreateWindowEx函式建立視窗時應指定WS_EX_LAYERED擴充套件樣式。

Windows 8: WS_EX_LAYERED擴充套件樣式支援頂級視窗和子視窗。之前的Windows版本中WS_EX_LAYERED擴充套件樣式僅支援頂級視窗

hdcDst

HDC

螢幕的裝置上下文(DC)控制代碼。如果指定為NULL

,那麼將會在呼叫函式時自己獲得。它用來在視窗內容更新時與調色盤顏色匹配。如果hdcDstNULL,將會使用預設調色盤。

如果hdcSrc指定為NULL,那麼hdcDst必須指定為NULL。

pptDst

POINT*

指向分層視窗相對於螢幕的位置的POINT結構的指標。如果保持當前位置不變,pptDst可初始化為0,0。

psize

SIZE*

指向分層視窗的大小的SIZE結構的指標。如果視窗的大小保持不變,psize可以初始化為0。如果hdcSrc指定為NULL,psize必須指定為NULL。

hdcSrc

HDC

分層視窗繪圖表面的裝置上下文控制代碼。這個控制代碼可以通過呼叫函式CreateCompatibleDC獲得。如果視窗的形狀和可視範圍保持不變,hdcSrc可以指定為NULL

pptSrc

POINT*

指向分層視窗繪圖表面在裝置上下文位置的POINT結構的指標。如果hdcSrc指定為NULL,pptSrc就應該指定為NULL。

crKey

指定合成分層視窗時使用的顏色值。要生成一個型別為COLORREF的值,使用RGB巨集。

pblend

指向指定合成分層視窗時使用的透明度結構的指標。

dwFlags

DWORD

可以是以下值之一。

如果hdcSrc指定為NULL,dwFlags應該指定為0。

意義

ULW_ALPHA

0x00000002

使用引數pblend作為混合函式,如果顯示模式為256色或低於256色,使用這個值實現的效果和使用ULW_OPAQUE的效果相同。

ULW_COLORKEY

0x00000001

使用引數crKey值作為透明顏色。

ULW_OPAQUE

0x00000004

繪製一個不透明的分層視窗。

示列程式碼:


#include <GdiPlus.h>

using namespace Gdiplus;
//匯入GDI+的庫

#pragma comment(lib, "Gdiplus.lib")

  void setWindow(HWND hWnd /*視窗控制代碼,必須具有WS_EX_LAYERED擴充套件風格*/) {
    //初始化gdi+

	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	//定義png的高與寬
	int img_h = 256;
	int img_w = 256;
	//申請記憶體dc與程式dc關聯
	HDC hDC = ::GetDC(hWnd);
	HDC hMemDC = ::CreateCompatibleDC(hDC);
	//申請一個位圖佈局
	BITMAPINFO bitmapinfo;
	bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitmapinfo.bmiHeader.biBitCount = 32;
	bitmapinfo.bmiHeader.biHeight = img_h;
	bitmapinfo.bmiHeader.biWidth = img_w;
	bitmapinfo.bmiHeader.biPlanes = 1;
	bitmapinfo.bmiHeader.biCompression = BI_RGB;
	bitmapinfo.bmiHeader.biXPelsPerMeter = 0;
	bitmapinfo.bmiHeader.biYPelsPerMeter = 0;
	bitmapinfo.bmiHeader.biClrUsed = 0;
	bitmapinfo.bmiHeader.biClrImportant = 0;
	bitmapinfo.bmiHeader.biSizeImage = bitmapinfo.bmiHeader.biWidth * bitmapinfo.bmiHeader.biHeight * bitmapinfo.bmiHeader.biBitCount / 8;
	//建立記憶體佈局
	HBITMAP hBitmap = CreateDIBSection(hMemDC, &bitmapinfo, 0, NULL, 0, 0);
	//選入記憶體
	HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
	//載入png影象
	Gdiplus::Image* pImage = Gdiplus::Image::FromFile(L"d:\\1.png");
	//讓gdi與記憶體dc關聯,將gdi裡的資料載入到記憶體位圖裡
	Graphics g(hMemDC);
	//設定記憶體點陣圖要顯示的區域,注意gdi會關聯到記憶體位圖裡
	g.DrawImage(pImage, RectF(0, 0, img_w, img_h), 0, 0, img_w, img_h, UnitPixel, NULL, NULL, NULL);
	delete pImage;	//刪除gdi
	//設定要顯示的座標
	Point DestPt(0, 0);
	Size psize(img_w, img_h);
	//點陣圖資訊
	BLENDFUNCTION blendFunc32bpp;
	blendFunc32bpp.AlphaFormat = AC_SRC_ALPHA;
	blendFunc32bpp.BlendFlags = 0;
	blendFunc32bpp.BlendOp = AC_SRC_OVER;
	blendFunc32bpp.SourceConstantAlpha = 255;
	//update更新到分層視窗上
	UpdateLayeredWindow(hWnd, hDC, NULL, (SIZE*)&psize, hMemDC, (POINT*)&DestPt, NULL, &blendFunc32bpp, ULW_ALPHA);
        ShowWindow(hWnd, SW_SHOW);

}

新增到窗口裡的完整程式碼:

#include <windows.h>



HWND hWnd;	//progman



			//訊息函式

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{

	//判斷訊息ID

	switch (uMsg) {



	case WM_DESTROY:    // 視窗銷燬訊息

		PostQuitMessage(0);   //  傳送退出訊息

		return 0;

	}

	// 其他的訊息呼叫預設的訊息處理程式

	return DefWindowProc(hwnd, uMsg, wParam, lParam);



}

// 3、註冊視窗型別

BOOL RegisterWindow(LPCSTR lpcWndName, HINSTANCE hInstance)

{

	ATOM nAtom = 0;

	// 構造建立視窗引數

	WNDCLASS wndClass = { 0 };

	wndClass.style = CS_HREDRAW | CS_VREDRAW;

	wndClass.lpfnWndProc = WindowProc;      // 指向視窗過程函式

	wndClass.cbClsExtra = 0;

	wndClass.cbWndExtra = 0;

	wndClass.hInstance = hInstance;

	wndClass.hIcon = NULL;

	wndClass.hCursor = NULL;

	wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

	wndClass.lpszMenuName = NULL;

	wndClass.lpszClassName = lpcWndName;    // 註冊的視窗名稱,並非標題,以後建立視窗根據此註冊的名稱建立

	nAtom = RegisterClass(&wndClass);

	return TRUE;

}

//建立視窗(lpClassName 一定是已經註冊過的視窗型別)

HWND CreateMyWindow(LPCTSTR lpClassName, HINSTANCE hInstance)

{

	HWND hWnd = NULL;

	// 建立視窗

	hWnd = CreateWindowEx(WS_EX_LAYERED,lpClassName, "test", WS_OVERLAPPEDWINDOW^WS_THICKFRAME, 0, 0, 1000, 800, NULL, NULL, hInstance, NULL);

	return hWnd;

}
//異型視窗開始
#include <GdiPlus.h>

using namespace Gdiplus;
//匯入GDI+的庫

#pragma comment(lib, "Gdiplus.lib")

GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
void DisplayMyWnd(HWND hWnd)

{
	//初始化gdi+

	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	//定義png的高與寬
	int img_h = 256;
	int img_w = 256;
	//申請記憶體dc與程式dc關聯
	HDC hDC = ::GetDC(hWnd);
	HDC hMemDC = ::CreateCompatibleDC(hDC);
	//申請一個位圖佈局
	BITMAPINFO bitmapinfo;
	bitmapinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitmapinfo.bmiHeader.biBitCount = 32;
	bitmapinfo.bmiHeader.biHeight = img_h;
	bitmapinfo.bmiHeader.biWidth = img_w;
	bitmapinfo.bmiHeader.biPlanes = 1;
	bitmapinfo.bmiHeader.biCompression = BI_RGB;
	bitmapinfo.bmiHeader.biXPelsPerMeter = 0;
	bitmapinfo.bmiHeader.biYPelsPerMeter = 0;
	bitmapinfo.bmiHeader.biClrUsed = 0;
	bitmapinfo.bmiHeader.biClrImportant = 0;
	bitmapinfo.bmiHeader.biSizeImage = bitmapinfo.bmiHeader.biWidth * bitmapinfo.bmiHeader.biHeight * bitmapinfo.bmiHeader.biBitCount / 8;
	//建立記憶體佈局
	HBITMAP hBitmap = CreateDIBSection(hMemDC, &bitmapinfo, 0, NULL, 0, 0);
	//選入記憶體
	HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
	//載入png影象
	Gdiplus::Image* pImage = Gdiplus::Image::FromFile(L"d:\\1.png");
	//讓gdi與記憶體dc關聯,將gdi裡的資料載入到記憶體位圖裡
	Graphics g(hMemDC);
	//設定記憶體點陣圖要顯示的區域,注意gdi會關聯到記憶體位圖裡
	g.DrawImage(pImage, RectF(0, 0, img_w, img_h), 0, 0, img_w, img_h, UnitPixel, NULL, NULL, NULL);
	delete pImage;	//刪除gdi
	//設定要顯示的座標
	Point DestPt(0, 0);
	Size psize(img_w, img_h);
	//點陣圖資訊
	BLENDFUNCTION blendFunc32bpp;
	blendFunc32bpp.AlphaFormat = AC_SRC_ALPHA;
	blendFunc32bpp.BlendFlags = 0;
	blendFunc32bpp.BlendOp = AC_SRC_OVER;
	blendFunc32bpp.SourceConstantAlpha = 255;
	//update更新到分層視窗上
	UpdateLayeredWindow(hWnd, hDC, NULL, (SIZE*)&psize, hMemDC, (POINT*)&DestPt, NULL, &blendFunc32bpp, ULW_ALPHA);
	//視窗中心顯示
	int scrWidth = GetSystemMetrics(SM_CXSCREEN);

	int scrHeight = GetSystemMetrics(SM_CYSCREEN);

	RECT rect;

	GetWindowRect(hWnd, &rect);

	ShowWindow(hWnd, SW_SHOW);

	//重新設定rect裡的值

	rect.left = (scrWidth - rect.right) / 2;

	rect.top = (scrHeight - rect.bottom) / 2;

	//移動視窗到指定的位置

	SetWindowPos(hWnd, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW);

	//settxt(editHwnd,"dasdas");
	//char *str = gettxt(editHwnd);
	//MessageBox(NULL, str, 0, 0);
	UpdateWindow(hWnd);


}



void doMessage()        // 訊息迴圈處理函式

{

	MSG msg = { 0 };

	// 獲取訊息

	while (GetMessage(&msg, NULL, 0, 0)) // 當接收到WM_QIUT訊息時,GetMessage函式返回0,結束迴圈

	{
		TranslateMessage(&msg);
		DispatchMessage(&msg); // 派發訊息,到WindowPro函式處理

	}

}



// 入口函式

int WINAPI WinMain(HINSTANCE hInstance,

	HINSTANCE hPrevInstance,

	LPSTR lpCmdLine,

	int nShowCmd)

{

	LPCTSTR lpClassName = "MyWnd";  // 註冊視窗的名稱

	RegisterWindow(lpClassName, hInstance);

	hWnd = CreateMyWindow(lpClassName, hInstance);

	DisplayMyWnd(hWnd);

	doMessage();

	return 0;

}

相關推薦

Windows核心程式設計_異型視窗

上一篇文章介紹的是使用SetLayeredWindowAttributes API來實現異型視窗,但是很明顯效果很差勁,在剔除顏色的過程中凹凸邊緣區域的畫素點會剔除的非常不明顯,在查詢資訊之後,得出的說法是當顯示屏在顯示影象的時候在顏色重疊的地方會產生顏色色差,而SetLa

Windows核心程式設計_異型視窗

異型視窗是Windows200在視窗中引入的WS_EX_LAYERED風格,並搭配:SetLayeredWindowAttributes API實現的,這裡所說的異型視窗不是指橢圓型的視窗或三角型之類的

windows核心程式設計--SEH結構異常處理

SEH 的工作原理。          Windows 程式設計中最重要的理念就是訊息傳遞,事件驅動。當GUI應用程式觸發一個訊息時,系統將把該訊息放入訊息佇列,然後去查詢並呼叫窗體的訊息處理函式(CALLBACK),傳遞的引數當然就是這個訊息。我們同樣可以把異常也當作是

Windows核心程式設計_遠執行緒方式實現Dll注入

之前有介紹過HOOK的方式注入,這次介紹以其它方式注入,而無須HOOK,要知道在Windows這個浩蕩的海洋裡,API就是寶藏,找到足夠多的寶藏那麼你就是海賊王~! 實現思路如下: 首先開啟一個程序的地址空間,然後開闢一塊空間將動態庫copy進去,然後找到動態庫要呼叫

C# WinForm Webbrowser 強制所有網頁連結在同一頁面開啟或者在TabControl中彈出新視窗

 上面那個文寫的如同粑粑一樣 效果圖   Winfrom 中新增這個類就好了 using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; u

python核心程式設計第三版學習筆記:正則表示式

注:下面有些內容不全都來源於原著,這些都是通過各方面的資料收集合並的結果。 目錄 1、元字元 3、邊界詞 4、分組詞 一、正則表示式介紹 正則表示式為高階的文字模式匹配、抽取、與/或文字形式的搜尋和替換功

Linux 核心程式設計之檔案系統

1.為了方便查詢,VFS引入了 目錄 項,每個dentry代表路徑中的一個特定部分。目錄項也可包括安裝點。 2.目錄項物件由dentry結構體表示 ,定義在檔案linux/dcache.h 標頭檔案中。   89struct dentry {  90        atomic_t d_count;     

Windows核心程式設計筆記二十 視窗與訊息2

喚醒一個執行緒 執行緒的掛起與喚醒 (1)當執行緒呼叫GetMessage或WaitMessage,而訊息佇列中又沒有訊息出現時,執行緒會被掛起。 (2)當訊息被“Post”(也可以是執行緒間的“Send”)到訊息佇列時,相應的Wake標誌位會被設定,以表明該執行緒

基於Visual C++之Windows核心程式設計程式碼分析1實現裝置管理器列舉裝置

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

基於visual c++之windows核心程式設計程式碼分析21獲取和設定環境變數

環境變數是一個具有特定名字的物件,它包含了一個或者多個應用程式所將使用到的資訊。例如path,當要求系統執行一個程式而沒有告訴它程式所在的完整路徑時,系統除了在當前目錄下面尋找此程式外,還應到path中指定的路徑去找。使用者通過設定環境變數,來更好的執行程序。 環境變數一

Windows核心程式設計筆記 執行緒排程 優先順序 關聯性

在搶佔式多工作業系統中,執行緒的執行是有限制的,系統會排程一個執行緒在一個時間塊內佔用CPU,在時間到了之後將執行緒的上下文(CONTEXT結構,儲存執行緒切換前的CPU個暫存器的值)儲存到執行緒核心物件中,從另一個可排程執行緒的CONTEXT中獲取屬於它的CPU各暫存器

基於visual c++之windows核心程式設計程式碼分析18遠端程式碼注入執行

我們進行系統級別的安全監控的時候,防範木馬的時候,經常需要進行遠端程式碼注入執行。執行步驟如下1. 提升程序許可權,如果許可權不夠的話,很容易造成 OpenProcess 失敗;2. 確定你的宿主程序,即你所要注入程式碼的程序,這個其實很好辦,你要是不想你的木馬或者病毒被別個

Windows核心程式設計筆記十八 SEH結構化異常 二

23.2 編譯器層面對系統SEH機制的封裝 23.2.1 擴充套件的EXCEPTION_REGISTRATION級相關結構:VC_EXCEPTION_REGISTRATION (1)VC_EXCEPTION_REGISTRATION結構 struct VC_EX

Windows核心程式設計筆記5----執行緒排程,優先順序

1、作業系統執行緒排程過程 每個執行緒都有一個上下文CONTEXT結構體,儲存線上程的核心物件中,這個上下文中儲存了執行緒上一次執行時CPU暫存器的狀態。每隔固定時間,Windows會檢視所有當前存在的執行緒核心物件,其中只有一些是可排程的。Windows在可排程的執行緒中

基於visual c++之windows核心程式設計程式碼分析61打造自己的Windows輸入法

IMM(Input Method Manager)只在安裝了亞洲語言包之後才能使用。通過呼叫GetSystemMetrics(SM_IMMENABLED)知道IMM是否使能。一共由三部分組成:status window  輸入法狀態列   表示正在處於中文輸入狀態可以知道是什

處理器_緩存cache

處理器 緩存4.處理器(續)_緩存(cache) 4.1硬件的處理速度 由於經濟因素,處理器和內存所使用的半導體工藝不同,工藝的差異導致了處理器和內存的速度差異,處理器總是要等待內存,處理器速度遠遠大於內存。所以在兩者之間增加緩存是及其必要的。通常:V處理 > V處理器內部寄存器 > V緩存

linux 核心模組程式設計之模組引數

通過巨集module_param指定模組引數,模組引數用於在載入模組時傳遞給模組。 module_param(name, type, perm) name是模組引數的名字 type是這個引數的型別,常見值:bool、int、charp(字串型) perm是模組

linux 核心模組程式設計之hello word

我們的目的是要編譯個hello.ko的檔案,然後安裝到核心中。 先來看下需要的程式碼,hello.c檔案如下 #include <linux/module.h> #include <linux/init.h> static int hello_init(vo

linux 核心模組程式設計之環境搭建

這裡介紹些關於Tiny6410開發板核心的編譯,為後期驅動開發做前期的準備。 開發環境:64位的Ubuntu 14.01虛擬機器 目標機:友善之臂Tiny6410開發板 核心:linux-2.6.38-20110325.tar.gz 核心原始碼下載地址 htt

管道的使用---參見Windows核心程式設計

   管道也是一種重要的程序間通訊方式,最近看了Windows核心程式設計裡面關於管道的理論及例子,覺得挺有意思,自己模擬著寫了一個,其中有些還是不太明白 尤其是服務端中的WaitForSingleObjectEx函式的返回值---WAIT-IO-COMPLETION,歡