https://www.petitmonte.com/bbs/answers?question_id=5715
いつもお世話になります。
タイトルの件について、リンク先を基に、OpenDialog上で「Alt + C」を押した
とき、ある動作をさせていたのですが、問題が生じてしまいました。
・Alt + Cを押したときの動作の内容
TOpenDialog上に自分でコンボボックスを追加しており、Alt + C
が押されたとき、そのコンボボックスにフォーカスを移動させると
いうもの。
(テキストエディタなどでよくある、文字コード判別のコンボボックス
のようなものと考えていただければと思います。)
・問題点
Alt + Cを押したとき、Windowsのサウンドを有効にしていたときに、
Beep音(のような音)が出てしまう。
・今まで試していた方法
CallNextHookExを呼び出さなければ音はならない。
でも、↓ここを見ると、他のソフトの動作に悪影響を与える可能性がある様子。
http://msdn.microsoft.com/ja-jp/library/cc429591.aspx
↓ここを見ると、HC_Skipなどというそれらしい識別子を利用している。
この辺を使うのかも知れないが、使い方がよく分からない。
http://www.swissdelphicenter.ch/torry/showcode.php?id=2004
・お聞きしたい事項
どのようにすれば、他のソフトに悪影響を出さず、Alt + Cを押したとき
の音を消せるか。
・具体的なコード (最上段のリンクからの引用です。)
var
HookHandle: HHOOK;
AltKeyDown: Boolean;
function KeyHook(Code: Integer; WParam: WPARAM; LParam: LPARAM): LRESULT; stdcall;
begin
if (Code >= 0)and(Code = HC_ACTION) then begin
if (LParam and $80000000) = 0 then begin
case WParam of
VK_MENU : AltKeyDown := True;
ORD('C'): if AltKeyDown then ShowMessage('ALT+C');
end;
end else begin
case WParam of
VK_MENU : AltKeyDown := False;
end;
end;
end;
result := CallNextHookEx(HookHandle, Code, WParam, LParam);
end;
書きもれてしまいました。追記させてください。
Windows XP Home + Delphi6 Personalを使用しています。
>Alt + C が押されたとき、そのコンボボックスにフォーカスを移動させる
という目的だったら、
コンボボックスの前にアクセスキー'&C'を持つラベルを置いておけば
あとはダイアログマネージャが面倒を見てくれるのではないでしょうか。
(ちなみにエラー音が鳴るのは、そのアクセスキーを持つコントロールが
ダイアログ上にないためだと思われます)
実際試したわけではないので自信はないですが、
ラベルはTWinControlの派生クラス(例えばTStaticText)でないといけないかもしれません。
後は、タブオーダーがラベル→コンボボックスの順になるように気をつければいけるかと。
一応実験コード
type
TCustomOpenDlg = class(TOpenDialog)
private
FComboBox: TComboBox;
FLabel: TStaticText;
protected
procedure DoShow; override;
public
constructor Create(AOwner: TComponent); override;
function Execute: Boolean; override;
end;
constructor TCustomOpenDlg.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLabel := TStaticText.Create(Self);
FLabel.Caption := 'コード(&C):'; // アクセスキーを設定
FComboBox := TComboBox.Create(Self);
end;
procedure TCustomOpenDlg.DoShow;
var
rc: TRect;
begin
// コントロールの親をダイアログにする
FLabel.ParentWindow := Handle;
FComboBox.ParentWindow := Handle;
// 適当に配置
rc := GetStaticRect;
FLabel.Left := rc.Right; FLabel.Top := rc.Top;
FComboBox.Left := rc.Right; FComboBox.Top := rc.Top + 16;
inherited DoShow;
end;
function TCustomOpenDlg.Execute;
begin
// TOpenPictureDialogの真似
if NewStyleControls and not (ofOldStyleDialog in Options) then
Template := 'DLGTEMPLATE' else
Template := nil;
Result := inherited Execute;
end;
これでAlt+Cでダイアログ内のコンボボックスにフォーカスが移動します。
ParentWindowを設定する必要があるので、やはりラベルはTStaticTextでないといけませんね。
ご回答、ありがとうございます。
先ほど、TLabelをTStaticTextに置き換えて動かしてみました。
そうしたところ、無事、動きました。もう少しだけ動作を検証させていただき、
その後で解決とさせていただきたいと思います。
TStaticTextというヒントだけでなく、わざわざ検証までしていただいて、
本当に頭の下がる思いです。本当にありがとうございました。
※せっかくなので、これを適用した際に新しく発生した問題点を参考までに書いておきます。
私の環境だけかもしれませんが、TCustomOpenDlg.Executeを2回以上実行すると、
なぜかStaticTextのCaptionが空文字("")になってしまう現象が発生しました。
(StaticTextの代わりにLabelを使っていたときは、こういう現象は全く起こらなかったのですが。)
これに対応するため、TCustomOpenDlg.DoShow;のタイミングで、Captionに文字列を設定
するという処理を追加で加えることとしました。
ご報告が遅れて申し訳ありません。
あの後、修正を適用後、しばらく使ってみながら同時に確認を行って
いたのですが、特に問題点等は発生しませんでした。ですので、これで
解決とさせていただきます。問題解決にあたり、ここでご回答をいただ
いたことは、非常に大きな助けとなりました。どうもありがとうござい
ました。
ツイート | ![]() |