問題タブ [windows-95]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
windows - モードレスフォームをタスクバーに正しく表示する方法
私は、モードレス フォームをタスクバーに表示するという古くからの Delphi の夢を実現しようとしています。
モードレス フォームをタスク バーに表示する正しい方法は何ですか?
研究努力
これらは問題を解決するための私の試みです。正しく動作させるには多くのことが必要です。タスクバーにボタンを表示するだけでは解決できません。Windows アプリケーションが Windows アプリケーションとして正しく動作するようにすることが、私の目標です。
私を知っている人、そして私の「ショーの研究努力」がどれほど深いものであるかを知っている人は、うさぎの穴をワイルドに駆け下りるので、ちょっと待ってください.
質問はタイトルと、上の水平線の上にあります。以下のすべては、頻繁に繰り返される提案の一部が正しくない理由を示すのに役立ちます.
Windows は、所有されていないウィンドウのタスクバー ボタンとしてのみ作成します
最初に、「メイン フォーム」があり、それから、この他のモードレス フォームを表示します。
これは新しいフォームを正しく表示しますが、タスクバーに新しいボタンは表示されません:
タスク バー ボタンが作成されないのは、これが設計上の理由によるものです。Windows は、 「所有されていない」ウィンドウのタスクバー ボタンのみを表示します。このモードレス Delphi フォームは、間違いなく所有されています。私の場合、所有者は次のApplication.Handle
とおりです。
私のプロジェクトの名前は、所有者に関連付けられModelessFormFail.dpr
た Windows クラス名の由来です。Modelessformfail
幸いなことに、ウィンドウが所有されている場合でも、Windowsに強制的にウィンドウのタスクバー ボタンを作成させる方法があります。
使うだけWS_EX_APPWINDOW
のMSDNドキュメントには次のようにWS_EX_APPWINDOW
書かれています:
WS_EX_APPWINDOW
0x00040000L
ウィンドウが表示されているときに、最上位ウィンドウを強制的にタスク バーに表示します。
スタイルをオーバーライドして手動で追加することも、よく知られた Delphi のトリックです。CreateParams
WS_EX_APPWINDOW
これを実行すると、新しく作成されたモードレス フォームは実際に独自のタスクバー ボタンを取得します。
そして、私たちは終わりましたか?いいえ、正しく動作しないためです。
ユーザーがfrmMainタスクバー ボタンをクリックしても、そのウィンドウは前面に表示されません。代わりに、他の形式 ( frmModeless ) が前面に出されます。
Windows の所有権の概念を理解すれば、これは理にかなっています。Windows は、設計上、子所有のフォームを前面に出します。所有者の上にフォームを保持することが、所有権の全体的な目的でした。
フォームを実際に非所有にする
解決策は、タスクバーのヒューリスティックやウィンドウと戦わないことです。フォームを非所有にしたい場合は、非所有にします。
これは(かなり)単純です。CreateParam
強制的に所有者ウィンドウは次のようになりますnull
。
余談ですが、PopupMode
とPopupParent
プロパティを使用してウィンドウを非所有にする方法があるかどうかを調査したかったのです。SO のどこかで (David からの) コメントを読んだことを誓います。Self
PopupParent
「所有者なし」を形成したいことをDelphiに示すための超秘密の方法であるはずでした。しかし、私は今どこにもコメントを見つけることができません。残念ながら、 と の組み合わせによってフォームが実際に非所有になることはPopupParent
ありません。PopupMode
- ポップアップモード: pmNone
- 所有者:
Application.Handle/Application.MainForm.Handle
- 所有者:
- ポップアップモード: pmAuto
- 所有者:
Screen.ActiveForm.Handle
- 所有者:
- PopupMode: pmExplicit
- PopupParent:なし
- 所有者:
Application.MainForm.Handle
- 所有者:
- ポップアップの親:
AForm
- 所有者:
AForm.Handle
- 所有者:
- PopupParent:自己
- 所有者:
Application.MainForm.Handle
- 所有者:
- PopupParent:なし
私ができることは、フォームに実際に所有者がいない可能性があります( Spy ++でチェックするたびに)。
WndParent
中に手動で設定するCreateParams
:
- フォームを非所有にします
- タスクバーボタンがあります
- 両方のタスクバー ボタンが正しく動作します。
これで終わりですよね?私はそうだと思いました。この新しいテクニックを使用するためにすべてを変更しました。
他の問題を引き起こすと思われる私の修正に問題があることを除いて - Delphi は私がフォームの所有権を変更することを好まなかった.
ヒントウィンドウ
モードレス ウィンドウのコントロールの 1 つにツールトップがあります。
問題は、このツールチップ ウィンドウが表示されると、他のフォーム (モーダル フォームであるfrmMain ) が前面に表示されることです。アクティベーション フォーカスは得られません。しかし、それは私が見ていたフォームを覆い隠しています:
理由はおそらく論理的です。Delphi HintWindowは、それが所有されるべきフォームによって所有されているのではなく、おそらくApplication.Handle
またはによって所有されています。Application.MainForm.Handle
私はこれを Delphi 側のバグと考えていたでしょう。間違った所有者を使用しています。
実際のアプリのレイアウトを見る転用
ここで、私のアプリケーションがメイン フォームでもモードレス フォームでもないことを示すために少し時間を割くことが重要です。
それは実際には:
- ログイン画面 (非表示になる犠牲的なメイン フォーム)
- メイン画面
- モーダル コントロール パネル
- モードレスフォームを示す
アプリケーションのレイアウトが現実的であっても、ヒント ウィンドウの所有権以外はすべて機能します。2 つのタスクバー ボタンがあり、それらをクリックすると適切なフォームが前面に表示されます。
しかし、HintWindow の所有権が間違った形式を進めるという問題がまだあります。
ShowMainFormOnTaskbar
問題を再現するために最小限のアプリケーションを作成しようとしていたときに、できないことに気づきました。何か違うものがありました:
- XE6に移植された私のDelphi 5アプリケーション間
- XE6 で作成された新しいアプリケーション
すべてを比較した後、最終的に XE6 の新しいアプリケーションはMainFormOnTaskbar := True
、新しいプロジェクトにデフォルトで を追加するという事実にたどり着きました (おそらく既存のアプリケーションを壊さないようにするためです):
このオプションを追加すると、ツールチップの外観が間違った形で表示されなくなりました!:
成功!ただし、何が来るかを知っている人は、何が来るかを知っています。私の「犠牲的な」メインログインフォームは、「実際の」メインフォームを表示し、それ自体を隠しています。
それが起こり、「ログイン」すると、タスクバーのアイコンが完全に消えます:
これは、次の理由で発生します。
- 所有されていない犠牲のメイン フォームは非表示ではありません。したがって、ボタンはそれと一緒に移動します。
- 実際のメイン フォームは所有されているため、ツールバー ボタンは取得されません。
WS_APP_APPWINDOW を使用
を使用する機会が得られましたWS_EX_APPWINDOW
。所有しているメイン フォームを強制的にタスク バーに表示したいと考えています。だから私はそれをオーバーライドCreateParams
して強制的にタスクバーに表示します:
そして、私たちはそれに渦を巻きます:
かなりいいですね!
- 2 つのタスクバー ボタン
- ツールチップは、間違った所有者フォームを前方にポップしません
ただし、最初のツールバー ボタンをクリックすると、間違ったフォームが表示されます。現在モーダルのfrmControlPanelではなく、モーダルのfrmMainを示しています。
おそらく、新しく作成されたfrmControlPanelがScreen.ActiveFormではなくApplication.MainFormに PopupParented されたためです。Spy++ をチェックインします。
はい、親はMainForm.Handle
です。これは、VCL の別のバグが原因であることが判明しました。フォームPopupMode
が次の場合:
- pmAuto
- pmNone (モーダルフォームの場合)
VCL はApplication.ActiveFormHandle
として使用しようとしますhWndParent
。残念ながら、モーダル フォームの親が有効になっているかどうかを確認します。
もちろん、モーダル フォームの親は有効になっていません。もしそうなら、それはモーダルフォームではありません。したがって、VCL は次の使用にフォールバックします。
手動子育て
これはおそらく、ポップアップのペアレンティングを手動で (?) 設定する必要があることを意味しますか?
それもうまくいかなかったことを除いて。最初のタスクバー ボタンをクリックすると、間違ったフォームがアクティブになります。
この時点で、私は完全に混乱しています。私のモーダル フォームの親はfrmMainである必要があります。
ならどうしよう?
私は何が起こっているのかという感覚を持っています。
そのタスクバー ボタンはfrmMainの表現です。Windowsはそれを前進させています。
MainFormOnTaskbarが false に設定されている場合を除いて、正しく動作しました。
Delphi VCL には、以前は正確さを引き起こした魔法があったはずですが、MainFormOnTaskbar := Trueで無効になりますが、それは何ですか?
Delphi アプリケーションが Windows 95 ツールバーで適切に動作することを望むのは、私が初めてではありません。過去にこの質問をしたことがありますが、それらの回答は常に Delphi 5 を対象としており、それは古い中央ルーティング ウィンドウです。
Delphi 2007 の期間中にすべてが修正されたと言われています。
では、正しい解決策は何ですか?
ボーナスリーディング
- http://blogs.msdn.com/b/oldnewthing/archive/2003/12/29/46371.aspx
- WS_EX_APPWINDOW は何をしますか?
- TsaveDialog を呼び出すと、詳細フォームがメイン フォームの後ろに隠れる
- The Oracle at Delphi ブログ: PopupMode と PopupParent
- DocWiki: Vcl.Forms.TForm.PopupMode
- DocWiki: Vcl.Forms.TCustomForm.PopupParent
- 非表示のメイン フォームで Delphi アプリケーションを起動するにはどうすればよいですか。
python-2.7 - Windows 95 上の Python 2.7 にパッケージをインストールする
ここで、Windows 9x用のpython 2.7.3のバージョンを見つけました。 http://www.msfn.org/board/topic/162317-python-27-for-windows-95/
Windows 95ラップトップで使用するためにダウンロードしました。これは珍しいことだと思いますので、問題が発生しても驚くことではありませんが、ピップでは発生しなかったため、新しいパッケージをインストールできません。get-pip.py を実行しようとしましたが、「AttributeError: function 'SHGetFolderPathW' not found, get-pip.pt がctypes からinit .py を使用しようとしているときに、いくつかの進行状況の後に失敗します。 Windows 2000 以降の dll に相当するのは、shfolder.dll の SHGetFileInfo だと思います。
SHGetFolderpathW を呼び出そうとするコードの部分を置き換えて、pip がインストールされるように (または少なくともさらに先に進むように) 置き換える方法がわかりません。
これは非常にニッチな問題であることはわかっていますが、誰かが助けてくれることを願っています。