0

予期しない動作をする Visual Studio 2012 (Professional) プロジェクトを作成しました。ダイアログが 1 つしかない場合、最初に TAB または ALT を押した後を除いて、それらを使用するときにコントロールにフォーカス四角形 (点線の境界線) が表示されません。プライマリ ダイアログの前に別のダイアログを (スプラッシュ スクリーンとして) ロードしようとすると、メイン (2 番目) のダイアログにフォーカス ドット ボーダー表示されます。これはなぜですか? また、これを防ぐにはどうすればよいですか?

ここに画像の説明を入力

私の唯一の推測では、ENTER または ESC を押すと、TAB または ALT を押すのと同じ種類の動作が発生し、ユーザーがスプラッシュ スクリーンを閉じるには ENTER または ESC を押す必要があるため、常にその効果が表示されます。コントロールからフォーカスを取り除く方法があったと思う人もいるかもしれませんが、それは簡単ではないようです。コントロールにフォーカスを簡単に設定できますが、一般的にそれを削除するだけではありません。

サンプルコードに興味のある方へ:


プロジェクトのコード全体を表示することもできますが、正直に自分でテストする方が簡単です。新しい VC++ プロジェクトを作成し、[MFC アプリケーション] を [ダイアログ ベース] に設定して、[完了] を選択します。リソース ビューで、[ダイアログ] を右クリックし、[ダイアログの挿入] をクリックします。メイン ウィンドウとは明確に異なるものにし、フォーカスできるコントロールを少なくとも 1 つ追加します。最後に、プライマリ .cpp ファイルの上部近くに、"// The one and only"... というテキストがあります。その下には、プライマリ アプリケーション オブジェクトを宣言する行があります。その行の下に新しいダイアログ クラスを作成し(「スプラッシュ スクリーン」については、下に私のものがあります*)、プライマリ アプリケーションの 内で、次のInitInstance()ような部分のすぐ上にスプラッシュ スクリーンをロードするコードを挿入します。

CDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();

スプラッシュ画面を表示するために使用したコードは次のとおりです。

CSplashDlg dlgSplash;
dlgSplash.DoModal();

*スプラッシュダイアログの私のコード:

更新: Enter キーを押す代わりに最初にダイアログをクリックできるようにコードを変更しました (実際、ある時点で pretranslatemsg() をオーバーライドし、ESC と ENTER をキャッチします。これが私の最新のコードです:

class CSplashDlg : public CDialogEx
{
public:
    CSplashDlg();
    enum { IDD = IDD_SPLASH };

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
};

CSplashDlg::CSplashDlg() : CDialogEx(CSplashDlg::IDD) {}

void CSplashDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); }

BEGIN_MESSAGE_MAP(CSplashDlg, CDialogEx)
    ON_WM_LBUTTONUP()
END_MESSAGE_MAP()

void CSplashDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
    EndDialog(1);
    CDialogEx::OnLButtonUp(nFlags, point);
}
4

2 に答える 2

1

ESC または ENTER を押すことは、TAB または ALT を押すこととプログラム的に似ているようです。これらのキーのいずれかを押すと、コントロールのフォーカス境界がトリガーされます。私の解決策は、デフォルトの「OK」および「CANCEL」オプションを使用するのではなく、ダイアログを手動で閉じることでした。これは、何らかの理由で、まだ作成されていない将来のダイアログでフォーカス境界をトリガーしました。

上に貼り付けた最新のコードが解決策です。最後の注意として、ユーザーがダイアログで ENTER または ESC を押さないようにすることも重要であることを指摘しておく必要があります (今はクリックが許可されていても、そうする可能性があります)。を使用してこれらのキープレスをキャッチしPreTranslateMessageます。このメソッドの使用中に ESCAPE と ENTER の使用を許可しながら、元の問題がまったく発生しないようにすることはおそらくできますがCSplashDlg::EndDialog(1);、PreTranslateMessage 呼び出しに含めるほど単純ではありません (試してみましたが失敗しました)。

私のCSplashDlgクラス定義では:

virtual BOOL PreTranslateMessage(MSG* pMsg);

そして、私の関数は次のようになります。

BOOL CSplashDlg::PreTranslateMessage(MSG* pMsg) {
    if ( pMsg->message == WM_KEYDOWN ) {
        if ( pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN ) {
            pMsg->wParam = NULL;
            //return MAKELONG(0,DC_HASDEFID);
        }
    }
    return CDialog::PreTranslateMessage(pMsg);
}
于 2013-02-21T22:51:30.967 に答える
0

OnInitDialog() のメイン ダイアログ (スプラッシュではない) でreturn FALSE;、最後のステートメントとして配置します。

于 2013-02-21T04:18:29.527 に答える