フォーラム


ゲスト  

ようこそ ゲスト さん。このフォーラムに投稿するには 登録が必要です。

ページ: [1]
トピック: TButton の Enabled := False の時の描画の問題
Mr.XRAY
メンバー
投稿数: 192
TButton の Enabled := False の時の描画の問題
on: 2013/05/17 11:24 Fri

実際に目にすることはあまりない現象かも知れませんが,ちょっとしたテストです.
Windows Vista 以降で,ランタイムテーマが有効な場合の現象です.
Delphi 7 では,uses に XPMan がある場合に相当します.

新規にプロジェクトを作成し,TButton を 2 つ配置し,各々のクリックイベントを以下のようにします.
どちらのクリックイベントも,最初に 2 つのボタンの Enabled プロパティの値を False にしています.

//-----------------------------------------------------------------------------
// uses に MMSystemが必要
//-----------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
StartTime : DWORD;
begin
Button1.Enabled := False;
Button2.Enabled := False;

StartTime := TimeGetTime;
//何かの処理の代わりとしてのループ
while True do begin
if (timeGetTime - StartTime) > 2000 then break;
Application.ProcessMessages;
Sleep(1);
end;

Button1.Enabled := True;
Button2.Enabled := True;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Button1.Enabled := False;
Button2.Enabled := False;

Sleep(2000);

//これがないとSleep中の操作が実行されてしまう
Application.ProcessMessages;
Button1.Enabled := True;
Button2.Enabled := True;
end;

  
これを実行すると下図のようになります.
Windows 7 + Delphi XE pro での実行結果です.
問題は,下の Button2 をクリックした時です.False の状態になっていないように見えます.
実際には False の状態になっていますが,描画が更新されていません.
Windows Vista 以降,画面でも明らかなように,デザインが変更されています.
処理内容によっては,コントロールの描画が追いつかないことがあります.
このような場合,意識的に Repaint を実行するか,少しタイムラグを付けて Repaint を実行すると描画が更新されます.


  
ランタイムテーマが無効であれば,この現象は発生しません.
下図は,Windows 7 + Delphi 7 Pro で,XPMan がない場合の結果です.


  
[参考]
[840_処理のキャンセル・画面更新の停止・キーやマウスの操作禁止]
http://mrxray.on.coocan.jp/Delphi/plSamples/840_CancellLockDisable.htm

追記
Twitter で見かけた書き込みでこの記事を書いたのですが,該当ツィートが見つかりません.
Twitter はそのような目的には適していないようです.
Twitter はリアルタイム用ですね.
本来は,[Windows システム Windows 固有の話題]だと思いますが,対象が TButton なのでこちらに書きました.

DEKO
管理者
投稿数: 2649
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/17 14:36 Fri

引用 Mr.XRAY on 2013/05/17 11:24 Fri
追記
Twitter で見かけた書き込みでこの記事を書いたのですが,該当ツィートが見つかりません.
Twitter はそのような目的には適していないようです.
Twitter はリアルタイム用ですね.

 
内容とは関係ありませんが、こっちに食いついてみます (w
仰るように Twitter は (技術的な) 質問には向いていません。

  • 読み逃したらその質問があったのかを調べるのですら困難 (面倒) 。
  • 情報共有という面ではその手段に疑問が残る。
  • 字数制限があるので回答を端折らざるを得ない。

Twitter での質問はそういう性格を持っているので、あらためて雑談にしたりココに書いたりしています。
(togetter というまとめの方法がない訳じゃないのですが、これまた面倒です)

即応性が欲しい場合には twitter でいいのですが、質問をツイートした時間に皆が皆手が空いているか?と言われればそうではない訳ですし。

arigayas
メンバー
投稿数: 3
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/17 15:19 Fri

Mr.XRAY さん、おかげさまでWindows 7 + Delphi XE pro + ランタイムテーマ有効状態で2つのボタンを無効に出来るようになりました。
試しにXP Mode上で試したら元々のコードでも2つのボタンが無効になることを確認できました。

ボタン2の処理の中にMessageDlgを出す処理を入れてあるとMessageDlgが呼ばれた時点で2つのボタンが無効になるので
最悪、ボタン1を押したのにMessageDlgで「実行しますか?」と聞こうかと思ってました。

追記へのレスです。

Twitter で見かけた書き込みでこの記事を書いたのですが,該当ツィートが見つかりません.

このツイートです。
https://twitter.com/arigayas/status/334877006460235777
このツイートは私が書いたブログ記事へのリンク
http://arigayas.exblog.jp/20449366/

Web:
Twitter>>https://twitter.com/arigayas
Blog>>http://arigayas.exblog.jp/

パソコン環境:
Windows 7 Professional SP1 64bit版 (+ XP Mode)
Delphi XE Professional

Mr.XRAY
メンバー
投稿数: 192
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/17 15:36 Fri

>質問をツイートした時間に皆が皆手が空いているか?

なんですよね.
そんなわけでここを利用させて頂いておりやす.
記事の修正はできるし,図は入れられるし,引用も便利だし(私は使っていないけど).
コードはインデントが付くし (笑)
Delphi ML みたいに,不要な引用もないし.
最初は,ジャンル分けが多くて,う~ん,と思ったのですが,結果的にはいいですね.

DEKO さんが折角つくってくれたコードの変換ですが,使うのやめました.
えっーと,コメントが斜体なのが好きでないのと,エディタで下書きする都合上,
余分なものがない方が編集しやすいので.
今のままで十分な可読性があると思います.

あっ,そうそう,コードの下に全角の空白を入れて,1 行の空きを作るという「技」を使っています.

Mr.XRAY
メンバー
投稿数: 192
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/17 15:41 Fri

>Twitter で見かけた書き込みでこの記事を書いたのですが,該当ツィートが見つかりません.

そうか,arigayas さんだったんですね.
たしか,昨日かなんか見かけたんですが,見つからなかったのではなく,
正確に言うと「面倒」だったんです.で,自分の Twitter に書いておけば見るかな~とおもっての手抜きです.

arigayas
メンバー
投稿数: 3
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/17 15:53 Fri

引用 Mr.XRAY on 2013/05/17 15:41 Fri
正確に言うと「面倒」だったんです.で,自分の Twitter に書いておけば見るかな~とおもっての手抜きです.

Twitterに流れてこなかったら解決しないままでした。ありがとうございます!!

Web:
Twitter>>https://twitter.com/arigayas
Blog>>http://arigayas.exblog.jp/

パソコン環境:
Windows 7 Professional SP1 64bit版 (+ XP Mode)
Delphi XE Professional

Mr.XRAY
メンバー
投稿数: 192
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/17 17:06 Fri

>意識的に Repaint を実行するか,少しタイムラグを付けて Repaint を実行すると描画が更新されます.

具体的には,例えば以下のようにします.

procedure TForm1.Button2Click(Sender: TObject);
begin
Button1.Enabled := False;
Button2.Enabled := False;
Sleep(100); // 追加
Button1.Repaint; // 追加

Sleep(2000);

//これがないとSleep中の操作が実行されてしまう
Application.ProcessMessages;
Button1.Enabled := True;
Button2.Enabled := True;
end;

 
最初のサンプルの結果のように, TButton.Enabled := False とした後の処理内容にもよります.
どのようなやり方がいいかは,ケースバイケースとなりそうです.

Mr.XRAY
メンバー
投稿数: 192
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/17 23:37 Fri

>Windows Vista 以降,画面でも明らかなように,デザインが変更されています.

例えば, Enabled := False にしないボタンを,マウスで (クリックではなく) ボタンを押す,という操作をしてみます.
ボタンの配色というか色の変化が,ランタイムテーマがない時の昔のものと明らかに違います.少し緩慢です.
Vista と 7 のウィンドウは複数の層 (レイヤー・フレーム) が描画されて,視覚的な効果を持たせています.
このフレームの描画,レンダリングに遅延があります.そのためです.
先ほどのコードで,

  Sleep(100);        // 追加
Button1.Repaint; // 追加

  
というのがありましたが,この Sleepの値を小さくしてしまうと,この遅延のため,再描画が正常に行われません.
この「遅延」は,キーボードのキーや,マウスクリックを,ものすごい操作するようなゲームアプリでは問題になることがあるかも知れません.

DEKO
管理者
投稿数: 2649
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/18 09:21 Sat

引用 Mr.XRAY on 2013/05/17 15:36 Fri
DEKO さんが折角つくってくれたコードの変換ですが,使うのやめました.
えっーと,コメントが斜体なのが好きでないのと,エディタで下書きする都合上,
余分なものがない方が編集しやすいので.
今のままで十分な可読性があると思います.

 
仕様変更してみました。
http://ht-deko.minim.ne.jp/delphiforum/?vasthtmlaction=viewtopic&t=1130.0#postid-1459

Mr.XRAY
メンバー
投稿数: 192
Re: TButton の Enabled := False の時の描画の問題
on: 2013/05/20 12:56 Mon

私のサイトに,すぐに動作確認できるように,EXE を同梱したプロジェクトファイルをダウンロードできるようにしました.
[700] [02_TButton の Enabled := False の時の描画の問題]
http://mrxray.on.coocan.jp/Delphi/plSamples/700_WaitSleep.htm#02

現実問題として,Sleep 関数だけを実行するだけのアプリケーションというのは考えにくいのですが,
あくまでも現象確認用のサンプルです.

ページ: [1]
WP Forum Server by ForumPress | LucidCrew
バージョン: 1.7.5 ; ページロード: 0.054 sec.