Edited at

C++ Builder > UtilWindowLocation > メインウィンドウの位置を9等分(3x3)のいずれかにする

More than 1 year has passed since last update.


動作環境

C++ Builder XE4



背景

複数のソフトを起動するとウィンドウが重なるが、XE4ではソフトの位置は以下のような選択肢しかない。


  • as designed

  • 中央 (画面、メインウィンドウ、etc)

だいたい9つの位置にメインウィンドウを配置する処理を作ってみた。


code v0.1


UtilWindowLocation.h

//---------------------------------------------------------------------------

#ifndef UtilWindowLocationH
#define UtilWindowLocationH

//---------------------------------------------------------------------------

/*
ソフトのメイン画面の位置調整用
厳密な調整ではなく、複数ソフト起動時に重なりを軽減する
*/

class CUtilWindowLocation {
private:
public:
enum {
V_AS_IT_IS, // 変更しない
V_TOP,
V_CENTER,
V_BOTTOM,
};
enum {
H_AS_IT_IS, // 変更しない
H_LEFT,
H_CENTER,
H_RIGHT,
};
static void __fastcall SetLocation(TForm *targetPtr, int vindex, int hindex);
static void __fastcall Test_SetLocation(TForm *targetPtr);
};

#endif



UtilWindowLocation.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "UtilWindowLocation.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

/*
v0.1 2017/10/25
- Test_SetLocation()追加
- SetLocation()追加
*/

/*static*/void __fastcall CUtilWindowLocation::SetLocation(TForm *targetPtr, int vindex, int hindex)
{
if (targetPtr == NULL) {
return; // error
}

targetPtr->Position = poDesigned; // Topなど位置変更を有効にするため

int mnttop = Screen->Monitors[0]->Top;
int mntleft = Screen->Monitors[0]->Left;

switch(vindex) {
case V_TOP:
targetPtr->Top = mnttop;
break;
case V_CENTER:
targetPtr->Top = mnttop + Screen->Monitors[0]->Height * 1 / 3;
break;
case V_BOTTOM:
targetPtr->Top = mnttop + Screen->Monitors[0]->Height * 2 / 3;
break;
}

switch(hindex) {
case H_LEFT:
targetPtr->Left = mntleft;
break;
case H_CENTER:
targetPtr->Left = mntleft + Screen->Monitors[0]->Width * 1 / 3;
break;
case H_RIGHT:
targetPtr->Left = mntleft + Screen->Monitors[0]->Width * 2 / 3;
break;
}
}

/*static*/void __fastcall CUtilWindowLocation::Test_SetLocation(TForm *targetPtr)
{
/*
実際の使用では、コンストラクタなどにSetLocation()をコールする
FormShow時に実行するとエラーになる。
*/

int hlist[] = { H_AS_IT_IS, H_LEFT, H_CENTER, H_RIGHT };
int vlist[] = { V_AS_IT_IS, V_TOP, V_CENTER, V_BOTTOM };
int numh = sizeof(hlist) / sizeof(hlist[0]);
int numv = sizeof(vlist) / sizeof(vlist[0]);

for(int hidx=0; hidx < numh; hidx++) {
for(int vidx=0; vidx < numv; vidx++) {
SetLocation(targetPtr, vlist[vidx], hlist[hidx]);
//
Application->ProcessMessages();
Sleep(1000);
}
}

}



使用例

Test_SetLocation()の実装を参考にCUtilWindowLocation::SetLocation()を使う。

FormShow時にはApplication->ProcessMessage()とSleep()は不要。

(FormShow時にはエラーとなるので、コンストラクタや別のタイミングで実施する)

Application->ProcessMessage()とSleep()はButtonClickイベント内での処理として使っているだけ。

試しに、以下のテスト実行をすると、ウィンドウが移動していく。

void __fastcall TFormMain::Button1Click(TObject *Sender)

{
CUtilWindowLocation::Test_SetLocation(this);
}


位置調整

位置調整を頑張りすぎると、モニタサイズ変更時におかしな配置になるだろう。

上記のような大雑把な調整とした。


関連

SketchUp Make v17 / Ruby > 複数のGroupを整列する > X方向

Unity > ScreenSizeKeeper