他のプログラムのコントロールの位置を移動させる


実行ファイルとソース move.ZIP

プログラムを起動させて移動したいボタンなどの上にマウスを置き、
CTRLキーを押しながらマウスを移動させます
ボタンなどが移動できます





■はじめに

あたりまえのことですけどWindowsはマウスで操作できますよね。
なぜマウスでボタンなどが操作できるか?どのように実現されているのか?
考えてみたいと思います

ボタンの上でマウスをクリックした瞬間のWindowsの処理(想像)
@マウスの現在の座標が読み取られる
Aその座標に対して現在表示されているコントロールのハンドルが取得される
B取得したハンドルにたいしてクリックを表すメッセージを送信する

つまりマウスのクリックは次の3つの関数で実現されていると考えられます
○マウスの座標を読み取る関数
○座標に対して現在表示されているハンドルを取得する関数
○ハンドルに対してメッセージを送信する関数

上記3つの関数は実はAPIとして公開されていて自由に使用することが出来ます
GetCursorPos	マウスの座標を読み取る
WindowFromPoint	座標に対して現在表示されているハンドルを取得する
SendMessage	ハンドルに対してメッセージを送信する

■コントロールの移動

VBやC#などで動的にコントロールの位置を変更する時には
そのコントロールに対して、右に移動しろとか左に移動しろとか命令をだしますよね
VB6で左移動ならば、Command1.Left = 10 でしょうか
その時に内部的に行われている動作は、コントロールのハンドル(識別子)に対して移動を促すメッセージが、送られているためです。

つまりコントロールを移動させるにはハンドルにメッセージを送信するのみで実現できるということです。


▼実際に移動させるには

ハンドルを取得する方法はマウスと同じ方法を使えば取得できます。
コントロールの移動は MoveWindow を使います
MoveWindowとはウィンドウを動かす関数です
ウインドウズのボタンやテキストボックスなどは、ウィンドウから作成されているため、MoveWindowを使えばウインドウからコントロールにいたるまで移動させることが出来ます

しかし、MoveWindowに与える座標は、ボタンの下のウィンドウに対する相対的な座標であったりします
マウスで取得できる座標は画面自体の座標であるため、その座標を変換しなければいけません
つまり、ボタンの下のウィンドウの座標が判らなければ変換できない事になります

そこで登場するのが座標を変換する関数
ボタンの下のウィンドウのハンドルを与える必要があります
ScreenToClient(hWnd,&pt)	座標をクライアントの座標に変換

▼ボタンの下のウィンドウのハンドルを取得する

座標に対して現在表示されているハンドルを取得する関数がありました
つまり、画面の見える部分のハンドルは取得することができます。

ということは、一瞬ボタンを見えなくして、下のウィンドウのハンドルを取得してボタンを元の状態に戻す
この動作を行えば、コントロールとその下のウィンドウのハンドルを取得できると考えられます
ShowWindow(hWnd,SW_HIDE)	見えなくする関数
ShowWindow(hWnd,SW_SHOW)	見えるようにする関数


これで総ての役者がそろいましたので実際のプログラムを作成します。


■実際のプログラム


#include <windows.h>

void move();

int main(){
	while(1){
		if(GetAsyncKeyState (VK_CONTROL)){
			//CTRLキーが押された
			move();
		}
		Sleep(1);
	}
	return 0;
}

void move(){
	POINT pt;
	//マウスの現在の座標を取得する
	GetCursorPos(&pt);
	HWND button_hWnd = WindowFromPoint(pt);//ボタンのハンドルを取得する
	ShowWindow(button_hWnd,SW_HIDE);//ボタンを消す
	Sleep(100);//少々待機
	GetCursorPos(&pt);
	HWND hWnd = WindowFromPoint(pt);//ハンドルを取得する
	ShowWindow(button_hWnd,SW_SHOW);//ボタンを表示させる
	//hWnd はボタンが配置されているウィンドウのハンドルとする
	//button_hWnd は移動するボタンのハンドルとする

	RECT re;
	GetWindowRect(button_hWnd,&re);//ボタンの画面上の座標を取得
	pt.x=re.left;//POINT構造体に代入
	pt.y=re.top;

	ScreenToClient(hWnd,&pt);//ボタンの座標をクライアントの座標に変換
	
	long size_x=re.right -re.left;
	long size_y=re.bottom-re.top;

	POINT o_pt;
	GetCursorPos(&o_pt);
	while(1){
		POINT m_pt,pos_pt;
		Sleep(10);
		GetCursorPos(&m_pt);
		pos_pt.x=m_pt.x-o_pt.x;
		pos_pt.y=m_pt.y-o_pt.y;
			if(pos_pt.x || pos_pt.y){
				MoveWindow(button_hWnd,pt.x+=pos_pt.x,pt.y+=pos_pt.y,size_x,size_y,1);//ボタンを移動
				o_pt=m_pt;
			}
		if(!GetAsyncKeyState (VK_CONTROL)) break;//CTRLキーが放された
	}
}




▲トップページ > プログラミングの実験