クリップボード監視によるラジオボタンの切り替えにて

解決


SOTO  2010-03-17 22:39:06  No: 38047

RadioGroupが配置してあり、このラジオボタンの切り替えを、
クリップボード監視により行なおうとしています。

クリップボード監視による切り替えには成功したのですが、
フォームをアクティブにすると、なぜか選択が元に戻ってしまいます。

何が原因なのか、わかる方がいらしたら、どうか教えて下さい。
よろしくお願いします。

以下、再現手順です。
1.新規作成し、RadioGroupをフォームに貼り付け、Itemsにアイテムを2個追加。
2.下記のコードをそっくりそのまま貼り付け。
3.実行し、ひとまず2個目のラジオボタンを選択。
4.メモ帳を起動して文字を入力し、その文字をクリップボードに記憶。
  するとラジオボタンの選択が切り替わる。
5.ところが、このソフトを選択してアクティブにすると選択が元に戻ってしまう。
  (メモ帳がアクティブだったのをこのソフトをアクティブにする)

//---------------------------------------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Clipbrd;

type
  TForm1 = class(TForm)
    RadioGroup1: TRadioGroup;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private 宣言 }

    FClipNextHandle: HWND;
    procedure WMDrawClipboard(var Msg: TWMDrawClipboard);
        message WM_DRAWCLIPBOARD;
    procedure WMChangeCBChain(var Msg: TWMChangeCBChain);
        message WM_CHANGECBCHAIN;

  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMDrawClipboard(var Msg: TWMDrawClipboard);
//クリップボード更新フック
//更新された後に流れてくる。
//アプリが立ち上がった瞬間も流れる
begin
  inherited;
//------------------------------
    //ShowMessage('クリップボード更新された');
    if Length(Clipboard.AsText) > 0 then
    begin
      RadioGroup1.ItemIndex := 0;
    end
    else
    begin
      RadioGroup1.ItemIndex := 1;
    end;
//------------------------------
  if FClipNextHandle<>0 then
    SendMessage(FClipNextHandle,WM_DRAWCLIPBOARD, 0, 0);
end;
procedure TForm1.WMChangeCBChain(var Msg: TWMChangeCBChain);
begin
  if Msg.Remove = FClipNextHandle then
    FClipNextHandle := Msg.Next;
  if FClipNextHandle <> 0 then
    SendMessage(FClipNextHandle, WM_CHANGECBCHAIN, Msg.Remove,Msg.Next);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  ChangeClipboardChain(Handle, FClipNextHandle);
end;
procedure TForm1.FormCreate(Sender: TObject);
    procedure ClipboardSetHandle;
    begin
      FClipNextHandle := SetClipboardViewer(Form1.Handle);
      if FClipNextHandle = 0 then
        if GetLastError <> 0 then
        begin
          //ShowMessage('クリップボードのフックに失敗');
        end;
    end;
begin
  ClipboardSetHandle;
end;
end.
//---------------------------------------------------------------------


再現  2010-03-18 01:11:48  No: 38048

>3.実行し、ひとまず2個目のラジオボタンを選択。
>4.メモ帳を起動して文字を入力し、その文字をクリップボードに記憶。
>  するとラジオボタンの選択が切り替わる。
>5.ところが、このソフトを選択してアクティブにすると選択が元に戻ってしまう。

試してみたら、その現象が起きることが確認できましたが、
以下のように 1行追加すれば それはもう起きませんね。

>  else
>  begin
>    RadioGroup1.ItemIndex := 1;
>  end;
   if Visible then RadioGroup1.SetFocus;  // この行を追加
>//------------------------------
>  if FClipNextHandle<>0 then
>    SendMessage(FClipNextHandle,WM_DRAWCLIPBOARD, 0, 0);
>end;


SOTO  2010-03-18 01:48:19  No: 38049

あ、ありがとうございました!

しかしこれは一体・・・??
原因がさっぱり予想つきません。
理由を教えて頂けたら幸いです。


結局  2010-03-18 03:32:35  No: 38050

ItemIndexを変えただけではボタンのフォーカスは移動せず、
Activeになった時にはフォーカスがあるボタンにチェックが戻って
しまうようですね。
クリックした時のように明示的にフォーカスを移すには以下のように
コードを書く必要があるということでしょうか。

if Visible then TWinControl(RadioGroup1.Controls[RadioGroup1.ItemIndex]).SetFocus;


SOTO  2010-03-19 23:12:05  No: 38051

大変、勉強にありました。
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加