tool
library
cppBuilder
geometry

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