【VBA×WindowsAPI】ClientToScreen関数の使い方

ClientToScreen関数

ClientToScreen関数はウィンドウのクライアント領域基準の座標をスクリーン基準の座標に変換するための関数です。クライアント領域とはタイトルバーや境界線などを除いたウィンドウのメイン描画部分のことです。VBAのUserformでコントロールを配置する際に使うLeft/Topプロパティはこのクライアント領域基準の座標となっています。

クライアント領域基準の座標はその領域の左上の地点を基準(原点)に、ウィンドウの水平方向をX軸、ウィンドウの垂直方向をY軸として2次元平面上の座標(x,y)で表すことができます。このとき座標の基準をスクリーンの左上とすることでスクリーン基準の座標(x’,y’)として表すこともできます。

ClientToScreen関数はこのクライアント領域基準の座標(x,y)をスクリーン基準の座標(x’,y’)に変換するための関数です。このとき変換する座標の単位はピクセル(px)となります。UserFormで使用するLeft/Topプロパティは単位がポイント(pt)のため、UserFormのコントロール等からスクリーン座標を取得する場合は事前に単位変換しておく必要があります。

ClientToScreen関数とは反対にスクリーン基準の座標をクライアント領域基準の座標に変換するためのScreenToClient関数という関数も存在します。状況によって使い分けることが可能です。

 

使用方法

ClientToScreen関数を使用するにはあらかじめ関数の宣言しておく必要があります。
※宣言をしないと関数は使えずにエラーとなるので書き忘れに注意しましょう。

使用しているWindowsが32bitか64bitかによって宣言時に書く文言が違います。
環境に合わせて以下のいずれかをコードの一番初め(Option Explicitの次の行あたり)に書いておくことで、そのモジュール内で各関数を使うことができるようになります。

 icon-code  64bit  

Declare PtrSafe Function ClientToScreen Lib “user32” _
(ByVal hwnd As LongPtr, lpPoint As POINTAPI) As Long

icon-code  32bit  

Declare Function ClientToScreen Lib “user32” _
(ByVal hwnd As Long, lpPoint As POINTAPI) As Long

上記のどちらを書けばいいかわからない場合は以下のコードをコピペして、モジュールの最上部に書いておきましょう。この構文を書いておくことで自動的に使うことのできる方の構文が使用されます。
VBE上では使えない方の構文が赤色で表示される場合がありますが、実行に影響はありません。

各関数の宣言文は「Private/Public」を付けて各関数の有効範囲を指定することもできます。

Private Declare PtrSafe Function~ :モジュール内でのみ呼び出し有効
Public Declare PtrSafe Function~ :モジュール外で呼び出し有効

 
引数に使われている「POINTAPI」は下記のように構造体として定義しておく必要があります。
座標を扱う関数で利用されることが多く、ある地点のx座標、y座標を格納するための構造体です。

 

構文

ClientToScreen関数の構文は下記のように書きます。

icon-code ClientToScreen関数 

lRet = ClientToScreen(hWnd, lpPoint)

引数

 hWnd    (64bit:LongPtr型 / 32bit:Long型) 

基準となるクライアント領域を持つウィンドウのハンドルを入力します。
このウィンドウのクライアント領域の座標からスクリーン座標に変換されます。

ウィンドウハンドルはFindWindow関数FindWindowEx関数GetActiveWindow関数などの関数で取得が可能です。ウィンドウハンドルは環境によって型が変化するので注意が必要です。
 

 lpPoint    (POINTAPI型) 

クライアント基準での座標が入ったPOINTAPI構造体を入力します。
事前に定義しているPOINTAPI構造体を使うことで下記のように、xとyに値を入れることが可能です。

たとえば上記の処理の後にこの「tCoord」を引数として入力すると、もう一方の引数hWndが示すウィンドウのクライアント領域基準の座標である「x=250」と「y=100」が、スクリーン基準の座標に変換され「tCoord」の中身を更新してくれます。(ByRefで入力しているため in/out を兼ねている)
 

戻り値

 lRet    (Long型) 

戻り値は関数が成功した場合は「0以外」です。
失敗した場合は「0」が返されます。

 

サンプルコード

以下はClientToScreen関数FindWindow関数を使って、メモ帳上の任意の点座標(250,100)をスクリーン基準の座標に変換するサンプルコードです。メモ帳を開いた状態で下記コードを実行するとメモ帳ウィンドウの位置に応じてウィンドウ上(クライアント領域)の座標をスクリーン上での座標値に変換することができます。

UserForm上のコントロールの位置(Top/Left/Width/Height)をスクリーン基準に変換する場合には単位をピクセル(px)に合わせるために下記のようなコードを書きます。

UserForm上の適当な位置に「Label1」というLebelコントロールを作成して、フォームのコードに下記コードを直接コピペしてください。その後、UserFormを起動するとLabel1の左上の点のスクリーン基準の座標がイミディエイトウィンドウに出力されます。スクリーン左上に持っていくとx,yがいずれも0に近づくことが確認できます。

 

 icon-share-square  VBA×WindowsAPIまとめページ

その他のWindowsAPI関数は下記ページにまとまっているので合わせて参照下さい。

 icon-share-square  参考

Microsoft公式:ClientToScreen 関数 (winuser.h) – Win32 apps

2024年3月2日Excel, VBA, Windows API

Posted by Lic