1つ質問をお願いします。
Delphi のコード補完ウィンドウのようなものを作ろうと思っています。
その補完ウィンドウをTFormで作っているのですが、補完ウィンドウを
表示させた後、メインウィンドウにフォーカスを移すという処理を
行うため、画面がちらついてしまいます。
フォーカスをメインウィンドウに置いたまま、補完ウィンドウを表示
させるにはどうすればよいでしょうか。
※1 補完ウィンドウのFormStyleは、fsStayOnTopに設定しています。
※2 環境はWinXP Home + Delphi6 です。
ウィンドウじゃなく、パネルにする。
ウィンドウじゃなく、別アプリにする。
とかの方が簡単にできると思いますが、こういうのはダメでしょうか?
ShowWindow + SW_SHOWNOACTIVATE
SetWindowPos + SWP_NOACTIVATE
とかで行けた気がします。
ただし一筋縄ではいかなかったことを記憶してます。
THintWindowを継承させた方が楽な気はしますが。
ご回答、どうもありがとうございます。
とりあえず、一番シンプルで分かりやすそうだった
ShowWindow + SW_SHOWNOACTIVATEを試してみました。
処理が無限ループ?に陥ってしまい、「一筋縄ではいかない」
を身をもって実感しました。キーワードが分かりましたので、
一歩前進したような気がします。これから検索して使える処理
がないか試してみます。
manbon様。
実は、最初の頃はそれを考えていました。ただ、エディタの場合、
横に並べた場合、横幅が非常に小さくなるようなことも考えられ、
単語とその単語の属性情報などを表示した場合、画面の右端がみ
えなくなってしまうのではと考え、別ウィンドウにしようとしました。
>>処理が無限ループ?に陥ってしまい
いあいあ、そもそもWindowアプリケーションは無限ループです。
直にAPIで表示状態を変更すると、
VCLのShow,Hideのメッセージの流れが変になります。
そのため必要な個所の修正が必要って意味です。
簡単な利用なだけであればさほど問題はありません。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private 宣言 }
PopForm : TForm;
btn : TButton;
procedure btnClick(Sender: TObject);
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnClick(Sender: TObject);
begin
Timer1.Enabled:=False;
ShowWindow(PopForm.Handle,SW_HIDE);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetWindowPos(PopForm.Handle,0,Left-100,Top-100,100,100,SWP_SHOWWINDOW or SWP_NOACTIVATE);
Timer1.Enabled := True;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Timer1.Enabled := False;
Timer1.Interval := 3000;
PopForm := TForm.Create(Self);
PopForm.BorderStyle := bsNone;
PopForm.Color := clYellow;
btn := TButton.Create(Self);
btn.Caption := 'Close';
btn.Parent := PopForm;
btn.OnClick := btnClick;
SetWindowPos(btn.Handle,0,0,0,100,100,SWP_SHOWWINDOW or SWP_NOACTIVATE);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
beep;
ShowWindow(PopForm.Handle,SW_HIDE);
end;
end.
Mr.XRAYです.
>表示させた後、メインウィンドウにフォーカスを移すという処理を
>行うため、画面がちらついてしまいます。
どんな処理をしているのかわかりせんが,以下のように,メインウィンドウであるフォームに
フォーカス移動するか,メインウィンドウのフォームに配置しているコントロールにフォーカス
移動するだけではダメということですか?
思いきっリ外しているのかも知れません.
procedure TForm1.Button1Click(Sender: TObject);
begin
//FormStyleはオブジェクト・インスペクタでの設定がbetter
Form2.FormStyle := fsStayOnTop;
Form2.Show;
//こんな処理を入れればこのフォームがアクティブ
Edit1.SetFocus;
//Form1.SetFocus;
end;
monaa様
わざわざコードまで示してくださって、ありがとうございます。
今日職場で試してきます。タイマーを使っている理由がまだよく
分からないのですが、少し試行錯誤して様子を見てみたいと
思います。
Mr.XRAY様
おっしゃるとおりです。実際には、fsStayOnTopを設定した
Form2を、
Form2.Show;
Form1.SetFocus;
という形で表示させていました。この場合、一瞬Form2に
フォーカスが移ったあと、Form1に戻るため、
Form2を頻繁に表示させたり消したりすると、ちらつきが
気になってしまいます。
Mr.XRAYです.
>Form2を頻繁に表示させたり消したりすると、ちらつきが
>気になってしまいます。
Form2の表示,非表示そのものをチラツキと言うのであれば,
これはどうしようもないような気がしますが.
ListBox 一個で済むものであれば・・・
type
TPopupList=class(TListBox)
private
FCursorIndex: Integer;
public
constructor Create(AOwner: TComponent); override;
protected
procedure CreateWnd; override;
procedure CreateParams(var Params:TCreateParams);override;
procedure Click; override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
end;
constructor TPopupList.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Height := ItemHeight * 6 + BorderWidth * 2;
end;
procedure TPopupList.CreateParams(var Params:TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_TOOLWINDOW;
end;
procedure TPopupList.CreateWnd;
begin
inherited CreateWnd;
Windows.SetParent(Handle, 0);
CallWindowProc(DefWndProc, Handle, WM_SETFOCUS, 0, 0);
end;
procedure TPopupList.Click;
begin
inherited Click;
Hide;
end;
procedure TPopupList.MouseMove(Shift: TShiftState; X, Y: Integer);
var
newIdx: Integer;
begin
newIdx := ItemAtPos(Point(X,Y), True);
if (newIdx <> FCursorIndex) then begin
Itemindex := newIdx;
FCursorIndex := newIdx;
Repaint;
end;
inherited MouseMove(Shift, X, Y);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
pl:TPopupList;
p:TPoint;
itm: TListItem;
begin
p := ClientToScreen(Point(Button1.Left + Button1.Width, Button1.Top + Button1.Height));
pl := TPopupList.Create(Self);
pl.Parent := Self;
pl.Items.Assign(Memo1.Lines);
pl.OnClick := ListBoxClick;
pl.Left := p.X;
pl.Top := p.Y;
pl.Show;
end;
procedure TForm1.ListBoxClick(Sender: TObject);
begin
if Sender is TListBox then begin
if TListBox(Sender).ItemIndex >= 0 then
Edit1.Text := TListBox(Sender).Items[TListBox(Sender).ItemIndex]
else
Edit1.Text := '未選択';
end;
end;
Mr.XRAYです.
>Form2を頻繁に表示させたり消したりすると、ちらつきが
>気になってしまいます。
どんなコードかも,具体的な動作仕様も,私にはわかりませんが,
Form2を表示する時に,このForm2(またはこの上のコントロール)に何かを表示
する際に,その表示がチラツクということなのでしょうか.
Form2なのか,Form2に表示するものなのか,切り分けが必要かも知れません
>Form2を頻繁に表示させたり消したりすると、ちらつきが
>気になってしまいます。
表示するのは,キー操作かマウスでしょうから.
人の手で,例えば1秒間に何十回もできないとは思いますが.
何十回もしたら,Form2の内容を見る余裕が?
この頻繁に,というのはどの程度なのかも問題なのかも.
Mr.XRAYです.
>Delphi のコード補完ウィンドウのようなものを作ろうと思っています。
ちょっと興味あったのでやってみました.
作ってみてから思ったのですが,単に別のフォームを表示して,リストから選択する
ということのようです.よくやる別の設定画面(別フォーム)を表示する方式と同じようですね.
ただ,違うのは,表示したフォームがポップアップメニューのような感じで現れる
ということのようです.つまり,枠のないフォームとでも言うのでしょうか.
別フォームを表示するだけではつまらないので,少しコードを付け足しています.
ただし,
>Form2を頻繁に表示させたり消したりすると、ちらつきが
>気になってしまいます。
の解決にはならないと思いますので,あくまで,何かの参考になればということです.
http://mrxray.on.coocan.jp/Delphi/plSamples/126_PopUpFormTest.htm
解決としておこう
ツイート | ![]() |