C++ Builder XE4, 10.2 Tokyo > フォームの座標位置 > WidthでなくClientWidthを使う (Win10対応)


ビルド環境
RAD Studio 10.2 Tokyo Update 2 + Windows 10 Pro (v1709)
実行環境
Windows 10 Pro (v1709)
Windows 8.1 Pro
Windows 7 Pro

関連

処理概要

フォームを並べるソフトを試していて、C++ Builder 10.2 Tokyoでビルドした場合にフォーム間に「空き」ができる。
さらに調べていると、10.2 Tokyoの問題ではなく、Windows 10での実行時に空きができるらしいことが見られた。

再現用のコードとして以下を試してみる。

Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TButton *B_makeDouble;
    void __fastcall B_makeDoubleClick(TObject *Sender);
private:    // ユーザー宣言
public:     // ユーザー宣言
    __fastcall TForm1(TComponent* Owner);
    __fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

TForm2 *s_forms[2] = {NULL, NULL};

void __fastcall TForm1::B_makeDoubleClick(TObject *Sender)
{
    // 1. フォームの作成
    if (s_forms[0] == NULL) {
        s_forms[0] = new TForm2(this);
    }
    if (s_forms[1] == NULL) {
        s_forms[1] = new TForm2(this);
    }
    s_forms[0]->Show();
    s_forms[1]->Show();

    // 2. 位置調整
    s_forms[1]->Top = s_forms[0]->Top;

    s_forms[0]->Left = this->Left + B_makeDouble->Left + B_makeDouble->Width;
    s_forms[1]->Left = s_forms[0]->Left + s_forms[0]->Width;

}

__fastcall TForm1::~TForm1()
{
    if (s_forms[0] != NULL) {
        delete s_forms[0];
    }
    if (s_forms[1] != NULL) {
        delete s_forms[1];
    }
}
//---------------------------------------------------------------------------

本来は右側の子フォームが左の子フォームにくっつくはずだが、そうはならない。

発生状況は以下の通り

  • Windows 10: 空きが生じる
  • Windows 8.1: 空きは生じない
  • Windows 7: 空きは生じない

Windows 10で「テキスト、アプリ、その他の項目のサイズを変更する」は「100%」でも「175%」でも同じように空きが生じる。
フォームのプロパティ「Scaled」をfalseにしても同じ。

座標の確認

Unit1.cpp
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift,
          int X, int Y)
{
    TPoint pt;

    pt = Mouse->CursorPos;

    String msg = IntToStr((int)pt.X) + L"," + IntToStr((int)pt.Y);
    OutputDebugString(msg.c_str());
}

マウス座標を表示するようにしてみた。
確認したところ、子フォームが縮小表示されているようだ。
(追記: この点は間違いだったようです)

関連

Vista以降の変更について記載されている。こちらでの確認ではVista以降というよりはWindows 10自体の違いの感じはする。
ClientWidthを使うという提案がされている。

実際にClientWidthに変更したら、下記のように子フォームが連結するようになった。

Windows8.1まで座標関係が問題なかったソフトもWindows 10で使用するときに変更することになるかもしれない(WidthからClientWidthへの変更)。

上記の理由

C++ Builder 10.2 Tokyo > WidthとClientWidthの違い on (Win7, Win8.1, Win10) > 同じように違う | フォーム外側の枠: Win10にはない
に見られるように、Windows 10においてウィンドウ枠(左、右、下)が表示されないことによるようだ。

この問題はXE4でビルドしたソフトでも生じるだろう。