(*--▽---------------------------▼-- Windowハンドルに対する処理関数群 2007/11/22(木) ・すでに GetProcessIDFromWinHandle/GetProcessFileNameFromWinHandle /GetWindowState/SetWinRect/GetWinRect /NoneTaskBarDesktopRect/UsingMonitorRect /GetDesktopRect/IsTopMostWnd /SetLayeredWindowAttributes/SetExStyle /SetTransparent /ForceForegroundWindow などは作成されている。 ・SetTransparentMultiを追加 2008/03/18(火) ・ClientRectToScreen/SetClientRect/CutRegionClientRectを実装 //--▲---------------------------△--*) unit WindowUnit; interface uses SysUtils, Forms, Windows, Messages, TLHelp32, Types, Controls, Graphics, RectPointUnit, XPtest; function GetProcessIDFromWinHandle(Handle: hWnd): Cardinal; function GetProcessFileNameFromWinHandle(Handle: hWnd): String; function GetWindowState(WndHandle: HWnd): TWindowState; procedure SetWinRect(Handle: THandle; Rect: TRect); function GetWinRect(AHandle: THandle): TRect; function NoneTaskBarDesktopRect: TRect; function UsingMonitorWorkareaRect: TRect; function MonitorWorkareaRect(TargetPoint: TPoint): TRect; function GetDesktopTop: Integer; function GetDesktopLeft: Integer; function GetDesktopHeight: Integer; function GetDesktopWidth: Integer; function GetDesktopRect: TRect; function GetCaptionBarHeight: Integer; function IsTopMostWnd(Target: HWND): boolean; procedure SetTopMostWnd(Target: HWND; const Value: Boolean); function SetLayeredWindowAttributes(hwnd: HWND; crKey: COLORREF; bAlpha: BYTE; dwFlags: DWORD): BOOL; stdcall; //function SetExStyle(WinHandle: Hwnd): Boolean; //function CancelExStyle(WinHandle: Hwnd): Boolean; function CheckExLayered(Handle: HWND): Boolean; function SetExLayered(Handle: Hwnd): Boolean; procedure CancelExLayered(Handle: Hwnd); procedure SetTransparent(WinHandle: Hwnd; Value: Byte); procedure SetTransparentMulti(Handles: array of DWORD; Value: Byte); procedure SetTransparentFadeOut(WinHandle: Hwnd; Value: Byte; Step: Byte = 8); procedure SetTransparentFadeOutMulti(Handles: array of DWORD; Value: Byte; Step: Byte = 8); procedure SetTransparentFadeIn(WinHandle: Hwnd; Value: Byte; Step: Byte = 8); procedure SetTransparentFadeInMulti(Handles: array of DWORD; Value: Byte; Step: Byte = 8); function AlphaValueToPercent(Value: Integer): Integer; function AlphaPercentToValue(Percent: Integer): Integer; function ForceForegroundWindow(hwnd: THandle): Boolean; function ClientRectToScreen(Control: TControl): TRect; procedure SetClientRect(F: TForm; R: TRect); procedure CutRegionClientRect(F: TForm); type TWindowStyle = record Visible: Boolean; ClipBlings: Boolean; ClipChildren: Boolean; Caption: Boolean; SysMenu: Boolean; ThickFrame: Boolean; MinimizeBox: Boolean; MaximizeBox: Boolean; end; function GetWindowStyle(WinHandle: Hwnd): TWindowStyle; procedure SetWindowStyle(WinHandle: Hwnd; Style: TWindowStyle); implementation {------------------------------- // ハンドルからProcessIDを得る関数 機能: 備考: uses TLHelp32; 参考:[Delphi:70691] Re: 実行ファイルのフルパスの取得(win2000) 履歴: 2006/05/07(日) 17:18 //--▼----------------------▽--} function GetProcessIDFromWinHandle(Handle: hWnd): Cardinal; //var // PID: Cardinal; begin Result := 0; // ハンドルから作成スレッドを調べてプロセスIDを得る GetWindowThreadProcessId(Handle, Result); end; //--△----------------------▲-- {------------------------------- // ハンドルからファイル名フルパスを得る関数 機能: 備考: uses TLHelp32; 参考:[Delphi:70691] Re: 実行ファイルのフルパスの取得(win2000) 履歴: 2006/05/07(日) 17:18 //--▼----------------------▽--} function GetProcessFileNameFromWinHandle(Handle: hWnd): String; var PID: Cardinal; SnapShot: THandle; ModuleEntry32: TModuleEntry32; begin Result := ''; // ハンドルから作成スレッドを調べてプロセスIDを得る GetWindowThreadProcessId(Handle, PID); // TModuleEntry32構造体の初期化 ModuleEntry32.dwSize := SizeOf( TModuleEntry32 ); // システム中の情報のスナップショットをとる SnapShot := CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, PID); try // 最初のモジュールの検索 if Module32First( SnapShot, ModuleEntry32 ) then Result := string( ModuleEntry32.szExePath ); finally CloseHandle( SnapShot ); end; end; //--△----------------------▲-- (*------------------------------- //ハンドルからWindowStateを調べる 引数説明: WndHandle: ハンドル -------------------------------*) function GetWindowState(WndHandle: HWnd): TWindowState; var pw : TWINDOWPLACEMENT; begin Result := wsNormal; pw.length := SizeOf(TWINDOWPLACEMENT); GetWindowPlacement(WndHandle, @pw); case pw.showCmd of SW_SHOWNORMAL:{=1} Result := wsNormal; SW_SHOWMINIMIZED: {=2} Result := wsMinimized; SW_MAXIMIZE: {=3} Result := wsMaximized; else // raise Exception.Create('WindowStateのエラー'+IntToStr(pw.showCmd)); // Assert(False, 'WindowStateのエラー'); end; end; {------------------------------- // Windowを指定位置に移動させる処理 機能: 備考: 履歴: 2006/05/24(水) 00:41 //--▼----------------------▽--} //↓廃止予定 //procedure MoveWindowRect(Handle: THandle; Rect: TRect); //begin // MoveWindow(Handle, Rect.Left, Rect.Top, // GetRectWidth(Rect), GetRectHeight(Rect), True); //end; procedure SetWinRect(Handle: THandle; Rect: TRect); begin MoveWindow(Handle, Rect.Left, Rect.Top, GetRectWidth(Rect), GetRectHeight(Rect), True); end; function GetWinRect(AHandle: THandle): TRect; begin GetWindowRect(AHandle, Result); end; //--△----------------------▲-- (*------------------------------- //タスクバーを除いたデスクトップの大きさを求める 備考: タスクバーのプロパティが 『常に手前に表示ON』『自動で隠すOFF』 の場合だけがResult.Top/Leftが0でなくなり Screen.Height/Width値とずれることになる 履歴: 2000/11/07 -------------------------------*) function NoneTaskBarDesktopRect: TRect; var rectDesktop : TRect; begin Result := Rect(0,0,0,0); if SystemParametersInfo(SPI_GETWORKAREA, 0, @rectDesktop, 0) then begin Result := rectDesktop; end; end; {------------------------------- // マルチディスプレイ環境でマウスのあるモニターのRectを返す関数 機能: 備考: 履歴: 2006/05/17(水) 11:55 //--▼----------------------▽--} function UsingMonitorWorkareaRect: TRect; var i: Integer; begin Result := Screen.DesktopRect; for i := 0 to Screen.MonitorCount - 1 do begin if PointInRect(Mouse.CursorPos, Screen.Monitors[i].BoundsRect) then begin Result := Screen.Monitors[i].WorkareaRect; end; end; end; //function UsingMonitorRect: TRect; //var // i: Integer; //begin // for i := 0 to Screen.MonitorCount - 1 do // begin // if PointInRect(Mouse.CursorPos, Screen.Monitors[i].WorkareaRect) then // begin // if Screen.Monitors[i].Primary then // begin // Result := NoneTaskBarDesktopRect; // end else // begin // Result := Screen.Monitors[i].WorkareaRect; // end; // end; // end; //end; //--△----------------------▲-- {--------------------------------------- 指定ポイントが含まれるモニターのRectを返す 機能: 備考: 履歴: 2011/06/23(木) ・ UsingMonitorWorkareaRectを流用して作成 }//(*----------------------------------- function MonitorWorkareaRect(TargetPoint: TPoint): TRect; var i: Integer; begin Result := Screen.DesktopRect; for i := 0 to Screen.MonitorCount - 1 do begin if PointInRect(TargetPoint, Screen.Monitors[i].BoundsRect) then begin Result := Screen.Monitors[i].WorkareaRect; end; end; end; //------------------------------------*) {------------------------------- // デスクトップサイズを求める 機能: マルチディスプレイ環境でも全てのウィンドウ含めた デスクトップサイズを求める事ができる 備考: TScreen.Desktop系プロパティからの抜粋 履歴: 2006/04/28(金) 22:00 作成 //--▼----------------------▽--} function GetDesktopTop: Integer; begin Result := GetSystemMetrics(SM_YVIRTUALSCREEN); end; function GetDesktopLeft: Integer; begin Result := GetSystemMetrics(SM_XVIRTUALSCREEN); end; function GetDesktopHeight: Integer; begin Result := GetSystemMetrics(SM_CYVIRTUALSCREEN); end; function GetDesktopWidth: Integer; begin Result := GetSystemMetrics(SM_CXVIRTUALSCREEN); end; function GetDesktopRect: TRect; begin Result := Bounds(GetDesktopLeft, GetDesktopTop, GetDesktopWidth, GetDesktopHeight); end; //--△----------------------▲-- {------------------------------- // ウィンドウのキャプションバーの高さを求める 機能: 備考: 履歴: 2007/12/30(日) 03:34 //--▼----------------------▽--} function GetCaptionBarHeight: Integer; begin // Result := GetSystemMetrics(SM_CYCAPTION); Result := GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME); end; //--△----------------------▲-- {------------------------------- // ハンドルから最善面かどうかを調べる関数 機能: 備考: 履歴: 2006/05/24(水) 01:28 2008/01/10(木) 20:40 Excelに対してはフラグとして SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOOWNERZORDER を指定する必要がある。 特にSWP_NOOWNERZORDERを指定することがポイント 参考: Vista?で?Excel?を最前面に表示する - Moo Soft http://maglog.jp/moosoft/Article205140.html //--▼----------------------▽--} function IsTopMostWnd(Target: HWND): boolean; begin Result := ((GetWindowLong(Target, GWL_EXSTYLE) and WS_EX_TOPMOST) <> 0); end; procedure SetTopMostWnd(Target: HWND; const Value: Boolean); begin if Value then begin // SetWindowPos(Target, HWND_TOPMOST, 0, 0, 0, 0, // SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE); SetWindowPos(Target, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOOWNERZORDER); end else begin // SetWindowPos(Target, HWND_NOTOPMOST, 0, 0, 0, 0, // SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE); SetWindowPos(Target, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOOWNERZORDER); end; end; //--△----------------------▲-- {------------------------------- // 透明化API処理 機能: SetLayeredWindowAttributesのAPI宣言 引数説明: hwnd : HWND 透明にするウィンドウのハンドル crKey: COLORREF 透過色 bAlpha: BYTE 透過度合 (0 = 完全透明 255 = 不透明) dwFlags: DWORD アクションフラグ(LWA_COLORKEY, LWA_ALPHA) LWA_COLORKEY 透明色として crKey を使います。 LWA_ALPHA bAlpha を使って、レイヤードウィンドウの不透明度を決定します。 備考: FadeOutが透明になる方、FadeInが不透明になる方 ↓使用例 begin SetLayeredWindowAttributes( Handle, ColorToRGB(clWindow), 200, LWA_ALPHA or LWA_COLORKEY); end; ↓SetLayeredWindowAttributes APIの詳細は以下のURLを参照 http://www.microsoft.com/japan/developer/library/psdk/jpuipf/_Win32_SetLayeredWindowAttributes.htm 参考: ・ サンプル: "透明なウィンドウ(Windows2000のみ)" http://forum.nifty.com/fdelphi/samples/00998.html ・ Nichiyo Delphian, Tips & Samples for Delphi http://www.d1.dion.ne.jp/~aide/misc/deltips/deltip06.html ・ [Delphi:44902] Win2k での半透明ウィンドウ 履歴: 2005/08/15 2008/01/08 CheckExLayered/ //--▼----------------------▽--} //↓Interface部にも以下のような宣言が必要 //function SetLayeredWindowAttributes(hwnd: HWND; crKey: COLORREF; // bAlpha: BYTE; dwFlags: DWORD): BOOL; stdcall; const WS_EX_LAYERED = $80000; LWA_COLORKEY = 1; LWA_ALPHA = 2; function SetLayeredWindowAttributes; external 'user32.dll' name 'SetLayeredWindowAttributes'; function CheckExLayered(Handle: HWND): Boolean; var Return: Longint; begin Return := GetWindowLong(Handle, GWL_EXSTYLE); if (Return and WS_EX_LAYERED) = WS_EX_LAYERED then begin Result := True; end else begin Result := False; end; end; function SetExLayered(Handle: Hwnd): Boolean; var i: Integer; var Return: Longint; begin Return := GetWindowLong(Handle, GWL_EXSTYLE); SetWindowLong(Handle, GWL_EXSTYLE, Return or WS_EX_LAYERED); {↑なんかちらつく?} i := 1; while (SetLayeredWindowAttributes(Handle, 0, 255, LWA_ALPHA)=False) do begin if 10 <= i then begin Result := False; Exit; end; Inc(i) end; {↑透明化スタイルWS_EX_LAYEREDをONにするために 不透明設定(LWA_ALPHAに255を設定)を Result=Trueになるまで繰り返している} Result := True; end; procedure CancelExLayered(Handle: Hwnd); var Return: Longint; begin Return := GetWindowLong(Handle, GWL_EXSTYLE); SetWindowLong(Handle, GWL_EXSTYLE, Return and not WS_EX_LAYERED); end; procedure SetTransparent(WinHandle: Hwnd; Value: Byte); begin SetLayeredWindowAttributes(WinHandle, 0, Value, LWA_ALPHA); end; procedure SetTransparentMulti(Handles: array of DWORD; Value: Byte); var j: Integer; begin for j := 0 to Length(Handles) - 1 do begin SetTransparent(Handles[j], Value); end; end; //透明になっていく procedure SetTransparentFadeOut(WinHandle: Hwnd; Value: Byte; Step: Byte = 8); var i: Integer; begin for i := 255 downto Value do begin if (i mod Step) <> 0 then continue; SetTransparent(WinHandle, i); end; SetTransparent(WinHandle, Value); end; procedure SetTransparentFadeOutMulti(Handles: array of DWORD; Value: Byte; Step: Byte = 8); var i, j: Integer; begin for i := 255 downto Value do begin if (i mod Step) <> 0 then continue; for j := 0 to Length(Handles) - 1 do begin SetTransparent(Handles[j], i); end; end; for j := 0 to Length(Handles) - 1 do begin SetTransparent(Handles[j], Value); end; end; //不透明になる procedure SetTransparentFadeIn(WinHandle: Hwnd; Value: Byte; Step: Byte = 8); var i: Integer; begin for i := Value to 255 do begin if (i mod Step) <> 0 then continue; SetTransparent(WinHandle, i); end; SetTransparent(WinHandle, 255); end; procedure SetTransparentFadeInMulti(Handles: array of DWORD; Value: Byte; Step: Byte = 8); var i, j: Integer; begin for i := Value to 255 do begin if (i mod Step) <> 0 then continue; for j := 0 to Length(Handles) - 1 do begin SetTransparent(Handles[j], i); end; end; for j := 0 to Length(Handles) - 1 do begin SetTransparent(Handles[j], 255); end; end; //--△----------------------▲-- {------------------------------- // AlphaBlend値を設定する時に%で指定するための関数 機能: AlphaBlend値は0〜255で指定する 0が完全に透明、255が不透明 これを透明度%で指定する時に変換する関数 100%が完全に透明、0%が不透明とする 備考: 履歴: 2008/03/13(木) //--▼----------------------▽--} function AlphaValueToPercent(Value: Integer): Integer; begin Result := (255 - Value) * 100 div 255; end; function AlphaPercentToValue(Percent: Integer): Integer; begin Result := (100 - Percent) * 255 div 100; end; //--△----------------------▲-- function ForceForegroundWindow(hwnd: THandle): Boolean; const SPI_GETFOREGROUNDLOCKTIMEOUT = $2000; SPI_SETFOREGROUNDLOCKTIMEOUT = $2001; var ForegroundThreadID: DWORD; ThisThreadID: DWORD; timeout: DWORD; begin if IsIconic(hwnd) then ShowWindow(hwnd, SW_RESTORE); if GetForegroundWindow = hwnd then Result := True else begin // Windows 98/2000 doesn't want to foreground a window when some other // window has keyboard focus if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and ((Win32MajorVersion > 4) or ((Win32MajorVersion = 4) and (Win32MinorVersion > 0)))) then begin // Code from Karl E. Peterson, www.mvps.org/vb/sample.htm // Converted to Delphi by Ray Lischner // Published in The Delphi Magazine 55, page 16 Result := False; ForegroundThreadID := GetWindowThreadProcessID(GetForegroundWindow, nil); ThisThreadID := GetWindowThreadPRocessId(hwnd, nil); if AttachThreadInput(ThisThreadID, ForegroundThreadID, True) then begin BringWindowToTop(hwnd); // IE 5.5 related hack SetForegroundWindow(hwnd); AttachThreadInput(ThisThreadID, ForegroundThreadID, False); Result := (GetForegroundWindow = hwnd); end; if not Result then begin // Code by Daniel P. Stasinski SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0), SPIF_SENDCHANGE); BringWindowToTop(hwnd); // IE 5.5 related hack SetForegroundWindow(hWnd); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(timeout), SPIF_SENDCHANGE); end; end else begin BringWindowToTop(hwnd); // IE 5.5 related hack SetForegroundWindow(hwnd); end; Result := (GetForegroundWindow = hwnd); end; end; { ForceForegroundWindow } {------------------------------- // スクリーン座標でClientRect位置を設定する処理 SetClientRect ClientRectをRegionで切り取る CutRegionClientRect 機能: 備考: Vistaの場合bsNoneでは浮き上がる効果がでないので Splashフォームを浮き上がらせる時に bsSizeableにしておいて、クライアント領域をRegionで 切り抜く必要があり、その為に作成 履歴: 2008/03/17(月) 10:47 //--▼----------------------▽--} function ClientRectToScreen(Control: TControl): TRect; begin Result.TopLeft := Control.ClientToScreen(Point(0,0)); Result.BottomRight := Control.ClientToScreen(Control.ClientRect.BottomRight); end; procedure SetClientRect(F: TForm; R: TRect); var ScreenClientRect, SetRect: TRect; TopLeftMove, BottomRightMove: TPoint; begin {↓現在のClientRectをスクリーン座標に変換} ScreenClientRect := ClientRectToScreen(F); {↓Rと現在のClientRectを比較} TopLeftMove.X := R.Left - ScreenClientRect.Left; TopLeftMove.Y := R.Top - ScreenClientRect.Top; BottomRightMove.X := R.Right - ScreenClientRect.Right; BottomRightMove.Y := R.Bottom - ScreenClientRect.Bottom; {↓現在のBoundRectに対してその移動量を求める} SetRect.Left := F.BoundsRect.Left + TopLeftMove.X; SetRect.Top := F.BoundsRect.Top + TopLeftMove.Y; SetRect.Right := F.BoundsRect.Right + BottomRightMove.X; SetRect.Bottom := F.BoundsRect.Bottom + BottomRightMove.Y; F.BoundsRect := SetRect; end; //クライアント領域の大きさでWindowを切り取る処理 procedure CutRegionClientRect(F: TForm); var ScreenClientRect, SetRect: TRect; TopLeftMove: TPoint; Rgn: HRGN; begin {↓ClientRectをスクリーン座標に変換} ScreenClientRect := ClientRectToScreen(F); {↓BoundRectとClientRectとの差を求める} TopLeftMove.X := ScreenClientRect.Left - F.BoundsRect.Left; TopLeftMove.Y := ScreenClientRect.Top - F.BoundsRect.Top; SetRect.Left := TopLeftMove.X; SetRect.Top := TopLeftMove.Y; SetRect.Right := TopLeftMove.X + F.ClientWidth - 1; SetRect.Bottom := TopLeftMove.Y + F.ClientHeight - 1; Rgn := CreateRectRgn(SetRect.Left, SetRect.Top, SetRect.Right, SetRect.Bottom); {↓リージョンをセット} setWindowRgn(F.Handle, Rgn, true); end; //--△----------------------▲-- {--------------------------------------- ウィンドウスタイルを GetWindowLong(hWnd, GWL_STYLE) /SetWindowLongで取得設定する 機能: 備考: 履歴: 2011/09/27(火) ・ 作成 }//(*----------------------------------- function APICheckInclude(Value, Flag: Integer): Boolean; begin if (Value and Flag)=0 then Result := False else Result := True; end; function GetWindowStyle(WinHandle: Hwnd): TWindowStyle; var Return: Longint; begin Return := Windows.GetWindowLong(WinHandle, GWL_STYLE); Result.Visible := APICheckInclude(Return, WS_VISIBLE); Result.ClipBlings := APICheckInclude(Return, WS_CLIPSIBLINGS); Result.ClipChildren := APICheckInclude(Return, WS_CLIPCHILDREN); Result.Caption := APICheckInclude(Return, WS_CAPTION); Result.SysMenu := APICheckInclude(Return, WS_SYSMENU); Result.ThickFrame := APICheckInclude(Return, WS_THICKFRAME); Result.MinimizeBox := APICheckInclude(Return, WS_MINIMIZEBOX); Result.MaximizeBox := APICheckInclude(Return, WS_MAXIMIZEBOX); end; procedure SetWindowStyle(WinHandle: Hwnd; Style: TWindowStyle); var Return: Longint; begin Return := 0; if Style.Visible then Return := Return or WS_VISIBLE; if Style.ClipBlings then Return := Return or WS_CLIPSIBLINGS; if Style.ClipChildren then Return := Return or WS_CLIPCHILDREN; if Style.Caption then Return := Return or WS_CAPTION; if Style.SysMenu then Return := Return or WS_SYSMENU; if Style.ThickFrame then Return := Return or WS_THICKFRAME; if Style.MinimizeBox then Return := Return or WS_MINIMIZEBOX; if Style.MaximizeBox then Return := Return or WS_MAXIMIZEBOX; SetWindowLong(WinHandle, GWL_STYLE, Return); end; //------------------------------------*) end.