いろいろと試してみたのですが、よく分かりません。
Form1や他のソフトの上に、Form2を常に上に表示したいんですが・・・
単純に
SetWindowPos(Form2.Handle,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE+SWP_NOSIZE);
で出来ると、思ったんですが、どうもうまくいかないのです。
上に出来たと思っても、別のアプリを交互にクリックすると、Form2が下に隠れてしまったり。
Delphi6なんですが、知っている方がいましたら、お願い致します。
如何?...
Form2.formstyle := fsStayOnTop;
SetWindowPos(Form2.Handle,HWND_TOP,0,0,0,0,SWP_NOMOVE+SWP_NOSIZE);
FormU2.Showmodal;
いろいろ手はありますが・・・
回答ありがとうございます。
まず、
実行すると、エラーになり、
>表示されているウィンドウをモーダルにすることはできません。
とでます。
//これは、アプリの中で一番上にするって事ですよね。
Form2.formstyle := fsStayOnTop;
//これが、ハンドルを指定して、上にする。
SetWindowPos(Form2.Handle,HWND_TOP,0,0,0,0,SWP_NOMOVE+SWP_NOSIZE);
//モーダルで表示する。
Form2.Showmodal;
モーダルってのが分からなかったので、調べてみました。
使えるメソッドなのですが、一つは、Form2を非表示にしていないとエラーが起きるのと、これでも、他のアプリの上にはなりません。
っていうか、普通同一アプリ?内なら、fsStayOnTopだけでいいのでは?
そうではなくて、Form2のみを、別のソフトやフォルダ表示も含めて、一番上にしたいのですが。
一応、試しにForm2.formstyle := fsStayOnTop;にして、
Timerで1秒ごとに、SetWindowPos(Form2.Handle,するのも考えたのですが、Form2が常にアクティブになるために、Form1の操作が不能になりました。
Form1をSetWindowPosにすれば、非アクティブの状態で、どのソフトの上にもなりますよね?
これをForm2のみにしたいのですが・・・。
お早うございます.Mr.XRAYです.
>これをForm2のみにしたいのですが・・・。
Form2が該当アプリのメインフォームでない場合は難しいですね.
以下は,表示するForm2のWindowProcのサブクラス化でやる方法です.
ただし,他のアプリが同じことをやっていると,動作は保障できまません.
>いろいろ手はありますが・・・
ということなので,方法,考え方の1つです.
同じDelphi6(Windows XP SP3)でテストしてみました.
Vistaでは正常動作しない場合もあります(アプリの構成による).
なお,
>Form2が常にアクティブになるために、Form1の操作が不能になりました。
----- メインフォーム(ここではForm1)からForm2を呼出すコード -----
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Show;
end;
---- Form2のコード -----
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private 宣言 }
public
{ Public 宣言 }
OriginalProc:TWndMethod;
procedure SubClassProc(var Message:TMessage);
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
//=============================================================================
// 元のWindowsProcを退避して新しいWindowProcを定義
//=============================================================================
procedure TForm2.FormCreate(Sender: TObject);
begin
OriginalProc := Self.WindowProc;
Self.WindowProc := SubClassProc;
end;
//=============================================================================
// アプリのメインフォームではないのでWindowsProcを元に戻しておく
// Form2を表示開始時にCreateする場合は不要
//=============================================================================
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Self.WindowProc := OriginalProc;
end;
//=============================================================================
// WindowProcのサブクラス
//=============================================================================
procedure TForm2.SubClassProc(var Message: TMessage);
//Targetが最前面かを判定する関数
function IsTopMost(Target: HWND): boolean;
begin
Result := ((GetWindowLong(Target, GWL_EXSTYLE) and WS_EX_TOPMOST) <> 0);
end;
//---------------------------------------------------------------------------
begin
OriginalProc(Message);
//このフォームが最前面でなければ最前面にする
if IsTopMost(Self.Handle)=False then begin
SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or SWP_NOOWNERZORDER);
end;
end;
end.
サブクラス化の参考ページ
http://mrxray.on.coocan.jp/Halbow/Notes/N004.html
>Form2が常にアクティブになるために、Form1の操作が不能になりました。
上記のコードでは,ということはないです.
Form1をクリック等してActiveにすれば操作可能です.
ただし,この場合でもForm2は最前面のままです.
大変失礼しました.
WindowsProcを元に戻すのはOnDestroyですね.OnCloseではなく.
procedure TForm2.FormDestroy(Sender: TObject);
begin
Self.WindowProc := OriginalProc;
end;
やはり、難しそうですね。
メインとサブを逆にすれば、もっと楽なんです。
Mr.XRAYさんの回答を試してみようと思います。
ありがとうございました。
解決です。
ツイート | ![]() |