←HSPハック トップへ

タスクバーのアイコンサムネイルの置き換え

Windows7 DWMAPIで導入された関数を使ってアイコンサムネイル(Iconic Thumbnail)を置き換えます。

最終更新:2017/11/18

初版:2017/11/18




はじめに


Windows 7 DWM(デスクトップマネージャ)APIにはアイコンサムネイルとライブプレビューをアプリケーションで置き換えできる機能があります。
この機能はタブブラウザ(IE、Mozilla Firefox)や、タブ機能付きエディタなどに使われています。

例:Mozilla Firefox)
Mozilla Firefox での例

置き換えまでの流れ


  1. DwmSetWindowAttribute 関数でウィンドウ属性を変更
  2. WM_DWMSENDICONICTHUMBNAIL メッセージが送られてきたときに、32bitビットマップを作成し、DwmSetIconicThumbnail 関数でビットマップを設定
意外と簡単に実装できます。

ウィンドウ属性の変更


DwmSetWindowAttribute 関数で変更します。
HRESULT WINAPI DwmSetWindowAttribute(
       HWND    hwnd,
       DWORD   dwAttribute,
  _In_ LPCVOID pvAttribute,
       DWORD   cbAttribute
);
hwnd に変更するウィンドウハンドルを指定します。
dwAttribute に適用するひとつの DWMWINDOWATTRIBUTE フラグを指定します。
pvAttribute にdwAttributeで指定された属性の値のポインタを指定します。
cbAttribute にpvAttributeが指す値の型のサイズを指定します。

サムネイルを置き換えするには、DWMWA_FORCE_ICONIC_REPRESENTATION(7)と、DWMWA_HAS_ICONIC_BITMAP(10)の属性の値を1に設定します。

サムネイルの置き換え


WM_DWMSENDICONICTHUMBNAIL メッセージが送られてきたタイミングでDwmSetIconicThumbnail 関数を使ってサムネイルを置き換えます。
HRESULT WINAPI DwmSetIconicThumbnail(
  _In_ HWND    hwnd,
  _In_ HBITMAP hbmp,
  _In_ DWORD   dwSITFlags
);
hwnd に変更するウィンドウハンドルを指定します。
hbmp にサムネイルとして使われる32bitのビットマップハンドルを指定します。
DWMは指定したビットマップをコピーして使用ますので、関数の呼び出しが終わったらDeleteObjectしてもかまいません。

dwSITFlags にサムネイルの表示オプションを指定します。
意味
0(0x00000000)サムネイルの周りにフレームを表示しない
DWM_SIT_DISPLAYFRAME(0x00000001)サムネイルの周りにフレームを表示する


指定するビットマップは32bitの色深度が必要です。
また、ビットマップのサイズは、WM_DWMSENDICONICTHUMBNAIL メッセージで指定されたサイズを使用します。 lParam値の上位ワードに最大幅が、lParam値の下位ワードに最大高さが入っています。

スクリプト


表示されたHSPウィンドウとは違うサムネイルを表示させるサンプルです。 buffer 1をサムネイルとして使います。
Screenshot

//HSP3.5から対応
//(c) inonote 2017
#packopt name "アイコンサムネイル置き換え"

#include "gdi32.as"
#include "user32.as"
#uselib "dwmapi.dll"
#func DwmSetIconicThumbnail "DwmSetIconicThumbnail" int, int, int
#func DwmSetWindowAttribute "DwmSetWindowAttribute" int, int, int, int

#define BI_RGB 0
#define HALFTONE 4
#define SRCCOPY 0x00CC0020

#define DWM_SIT_DISPLAYFRAME 0x00000001
#define WM_DWMSENDICONICTHUMBNAIL 0x0323
#enum DWMWA_NCRENDERING_ENABLED = 1
#enum DWMWA_NCRENDERING_POLICY
#enum DWMWA_TRANSITIONS_FORCEDISABLED
#enum DWMWA_ALLOW_NCPAINT
#enum DWMWA_CAPTION_BUTTON_BOUNDS
#enum DWMWA_NONCLIENT_RTL_LAYOUT
#enum DWMWA_FORCE_ICONIC_REPRESENTATION
#enum DWMWA_FLIP3D_POLICY
#enum DWMWA_EXTENDED_FRAME_BOUNDS
#enum DWMWA_HAS_ICONIC_BITMAP
#enum DWMWA_DISALLOW_PEEK
#enum DWMWA_EXCLUDED_FROM_PEEK
#enum DWMWA_CLOAK
#enum DWMWA_CLOAKED
#enum DWMWA_FREEZE_REPRESENTATION
#enum DWMWA_LAST

#define ctype HIWORD(%1) ((%1>>16)&0xFFFF)
#define ctype LOWORD(%1) ((%1)&0xFFFF)

buffer 1 //サムネ用画像バッファ
color 122, 0, 122:boxf
color 0, 0, 0:font "MS 明朝", 128
mes "サムネ\n置き換え済"

screen 0
color 122, 255, 122:boxf
color 0, 0, 0:font "MS ゴシック", 128
mes "あいうえお"

oncmd gosub *OnSendIconicThumbnail, WM_DWMSENDICONICTHUMBNAIL

// ウィンドウの属性を変更してサムネを変更できるようにする
trueValue=1
DwmSetWindowAttribute hwnd, DWMWA_FORCE_ICONIC_REPRESENTATION, varptr(trueValue), 4
DwmSetWindowAttribute hwnd, DWMWA_HAS_ICONIC_BITMAP, varptr(trueValue), 4

stop
*OnSendIconicThumbnail //サムネイルを求めた
	SetIconicThumbnailFromBuffer hwnd, HIWORD(lparam), LOWORD(lparam), 1
return 0

//SetIconicThumbnailFromBuffer ウィンドウハンドル, サムネサイズX, サムネサイズY, サムネにするバッファID
#deffunc SetIconicThumbnailFromBuffer int hnd, int sx, int sy, int bufferid
	dim Rect, 4
	oldbufferid = ginfo_sel
	gsel bufferid
	Rect = 0, 0, ginfo_sx, ginfo_sy
	
	//サムネイル用 32bit ビットマップ作成
	dim OutRect, 4
	OrgRect = 0, 0, Rect(2), Rect(3)
	wRect=0, 0, sx, sy
	FitInRect OutRect, wRect, OrgRect //求められた大きさに収める
	thmx = OutRect(2):thmy = OutRect(3)
	imagesize = thmx*thmy*4
	bmi = 40, thmx, thmy, 1|(32<<16),BI_RGB, imagesize
	
	hdc_thumb = CreateCompatibleDC(0) //デバイスコンテキスト作成
	hbmp_thumb = CreateDIBSection(0, varptr(bmi), 0, varptr(lpBits), 0, 0) //ビットマップ作成
	if (hbmp_thumb){
		hOldBmp1 = SelectObject(hdc_thumb, hbmp_thumb)
		SetStretchBltMode hdc_thumb, HALFTONE //伸縮モード変更
		hPal = CreateHalftonePalette(hdc_thumb) //ハーフトーンパレット作成
		hOldPal = SelectPalette(hdc_thumb, hPal, 0)
		RealizePalette hdc_thumb //論理パレットを実体化
		StretchBlt hdc_thumb, 0, 0, thmx, thmy, hdc, 0, 0, Rect(2), Rect(3), SRCCOPY //伸縮コピー
		
		//あと片付け
		SelectPalette hdc_thumb, hOldPal, 0
		DeleteObject hPal
		SelectObject hdc_thumb, hOldBmp1
	}
	DeleteDC hdc_cwnd
	DwmSetIconicThumbnail hnd, hbmp_thumb, DWM_SIT_DISPLAYFRAME //サムネイルに設定
	DeleteObject hbmp_thumb
	
	gsel oldbufferid
return

#module
	//FitInRect 出力先(RECT構造体), 収める大きさ(RECT構造体), 元の大きさ(RECT構造体)
	//縦横比を保持しながら、収める大きさまで拡大縮小します。
	#deffunc FitInRect array OutRect, array Rect, array OrgRect
		if length(Rect)!=4:return 0
		if length(OrgRect)!=4:return 0
		dim OutRect,4
		OutRect=Rect(0),Rect(1),Rect(2),Rect(3)
		if (OrgRect(2)-OrgRect(0))>(OrgRect(3)-OrgRect(1)){//横のほうが長い
			OutRect(2)=Rect(2)//横いっぱいに
			OutRect(3)=int(double(OrgRect(3))*(double(Rect(2))/double(OrgRect(2))))
		}else:if (OrgRect(2)-OrgRect(0))<(OrgRect(3)-OrgRect(1)){//縦のほうが長い
			OutRect(3)=Rect(3)//縦いっぱいに
			OutRect(2)=int(double(OrgRect(2))*(double(Rect(3))/double(OrgRect(3))))
		}
		
		if (OutRect(2)-OutRect(0))>(Rect(2)-Rect(0)){//横のほうが長い
			old=OutRect(2)
			OutRect(2)=Rect(2)//横いっぱいに
			OutRect(3)=int(double(OutRect(3))*(double(Rect(2))/double(old)))
		}else:if (OutRect(3)-OutRect(1))>(Rect(3)-Rect(1)){//縦のほうが長い
			old=OutRect(3)
			OutRect(3)=Rect(3)//縦いっぱいに
			OutRect(2)=int(double(OutRect(2))*(double(Rect(3))/double(old)))
		}
	return
#global




[前へ] [戻る] [次へ]

(C)2019 inonote / 無断転載禁止