LoginSignup
0
1

More than 5 years have passed since last update.

C++ Builder 10.2 Tokyo > Forms > Height > Windows 10: 実行タイミングによって異なる | Windows 7, 8.1: 実行タイミングによらず同じ > FormShow時とFormShow後

Last updated at Posted at 2018-05-07
動作環境
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の値が異なる。

  1. FormShow時
  2. 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では実行されない。

関連

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1