動作環境
RAD Studio 10.2 Tokyo Update 3
秀丸エディタ Version 8.79
関連
C++ Builder 10.2 Tokyo > Forms > フォームを並べたときに空白がないように配置する (Windows 7, 8.1, 10) > FormShow後の実行
上記にてWindows 10でもフォーム間のマージンが発生しないような実装をしていた。
しかしながら、マージンが発生する状況が見つかった。
Heightの違い
Windows 10においては、下記の処理にてHeightの値が異なる。
- FormShow時
- FormShow後
このため、FormShow時にフォーム位置を調整する処理を実行すると失敗する。
確認コード
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 *Button1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormShow(TObject *Sender);
private: // ユーザー宣言
void __fastcall getVisibleWindowSize(TForm *formPtr, TRect *rectPtr);
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::getVisibleWindowSize(TForm *formPtr, TRect *rectPtr)
{
TRect arect_inv;
RECT arect_nrm;
if (formPtr == NULL || rectPtr == NULL) {
return; // error
}
GetWindowRect(formPtr->Handle, &arect_nrm); // (1)
DwmGetWindowAttribute(formPtr->Handle, DWMWA_EXTENDED_FRAME_BOUNDS, &arect_inv, sizeof(TRect)); // (2)
// for Windows 7
if (arect_inv.left == 0 && arect_inv.top == 0 && arect_inv.Bottom == 0 && arect_inv.right == 0) {
// DwmGetWindowAttribute()が0を返すためGetWindowRect()の結果を使う
rectPtr->left = arect_nrm.left;
rectPtr->top = arect_nrm.top;
rectPtr->right = arect_nrm.right;
rectPtr->bottom = arect_nrm.bottom;
return;
}
// for Windows 8.1, Windows 10
// Windows 8.1では(1)と(2)は同じ定義
// Windows 10ではinvisible borderにより(1)と(2)の結果が異なる
// invisible borderのサイズを含まない(2)の方を返す
//
// !!!ただしWindows 10の場合、FormShow時には正しい値を返さない!!!
// FormShow後に実行すること
rectPtr->left = arect_inv.left;
rectPtr->top = arect_inv.top;
rectPtr->right = arect_inv.right;
rectPtr->bottom = arect_inv.bottom;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRect arect;
getVisibleWindowSize(this, &arect);
int parhei = arect.Bottom - arect.top;
String msg = IntToStr(parhei) + L" on Button1Click()";
ShowMessage(msg);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
TRect arect;
getVisibleWindowSize(this, &arect);
int parhei = arect.Bottom - arect.top;
String msg = IntToStr(parhei) + L" on FormShow()";
ShowMessage(msg);
}
//---------------------------------------------------------------------------
実行
BorderStyle = bsSizeableの場合
-
Windows 7
- 337 on FormShow()
- 337 on Button1Click()
-
Windows 8.1
- 338 on FormShow()
- 338 on Button1Click()
-
Windows 10
- 338 on FormShow()
- 331 on Button1Click()
BorderStyle = bsDialogの場合
-
Windows 7
- 337 on FormShow()
- 337 on Button1Click()
-
Windows 8.1
- 348 on FormShow()
- 348 on Button1Click()
-
Windows 10
- 338 on FormShow()
- 336 on Button1Click()
BorderStyle = bsSingleの場合
-
Windows 7
- 337 on FormShow()
- 337 on Button1Click()
-
Windows 8.1
- 348 on FormShow()
- 348 on Button1Click()
-
Windows 10
- 338 on FormShow()
- 336 on Button1Click()
移植時の問題
Windows 7とWindows 8.1で問題なく動作していたソフトはWindows 10において位置がおかしくなるかもしれない。
FormResize時
FormResize時の処理はFormShow後と同じ値となる。
FormResizeが実行されるのはBorderStyle = bsSizeableの場合。bsSingleやbsDialogでは実行されない。