CPropertySheetのタブオーダーの変更

このQ&Aのポイント
  • MFCを使ったダイアログアプリでCPropertySheet, CPropertyPageを使用してタブで切り替えの出来るUIを作成しようとしています。
  • CSheetをメインダイアログのOnInitDialogでCreateして,メインダイアログ内に貼り付けて使用しています。
  • タブオーダーが(メインダイアログ内のコントロール)→(CPage内のコントロール)→(タブ)という順番になっており、これを(メインダイアログ内のコントロール)→(タブ)→(CPage内のコントロール)に変更したいです。PretransMessageでTABキー押下イベントを横取りし、フォーカスの移動順を変更することはできましたが、よりスマートな方法があれば教えてください。
回答を見る
  • ベストアンサー

CPropertySheetのタブオーダーの変更

MFCを使ったダイアログアプリでCPropertySheet, CPropertyPageを 使用してタブで切り替えの出きるUIを作成しようとしています。 (WindowsXP Pro sp2, .NET2003) 以下のようにCPropertySheet, CPropertyPageの派生クラスを作成し, CPropertySheetの派生クラスのコンストラクタでCPropertyPageの 派生クラスをAddPageしています. class CPage : public CPropertyPage {   DECLARE_DYNAMIC(CPage) public:   CPage();   virtual ~CPage();   enum { IDD = IDD_PAGE }; protected:   DECLARE_MESSAGE_MAP() } class CSheet : public CPropertySheet {   DECLARE_DYNAMIC(CSheet) private:   CPage m_page; public:   CSheet(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0);   virtual ~CSheet(); protected:   DECLARE_MESSAGE_MAP() }; CSheet::CSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)   :CPropertySheet(nIDCaption, pParentWnd, iSelectPage) {   AddPage( &m_page ); } 上記のCSheetをメインダイアログのOnInitDialogでCreateして, メインダイアログ内に貼り付けて使用しています. m_sheet = new CSheet( "", this ); m_sheet->Create( this, WS_CHILD|WS_VISIBLE, WS_EX_CONTROLPARENT ); これで,タブオーダーが(メインダイアログ内のコントロール)→(CPage内のコントロール)→(タブ)という順番になってしまっています. これを(メインダイアログ内のコントロール)→(タブ)→(CPage内のコントロール)に変更することは可能でしょうか? PretransMessageでTABキー押下イベントを横取りし,無理やり フォーカスの移動順を変更した場合には,うまくできましたが, もう少しスマートな方法はないかと思い投稿させていただきました. 宜しくお願い致します.

質問者が選んだベストアンサー

  • ベストアンサー
  • clsdi99
  • ベストアンサー率63% (31/49)
回答No.1

いちおう思い通りの動作ができているようですので、お困りではないようですが^^; PretranslateMessageを使うのがスマートじゃないかというところは微妙ですが、そのダイアログ内のコントロールのタブオーダーを変更してみるというのも手かもしれませんね。(SetWindowPosでZORDERを変えるとか) 例えばしょっちゅうこのような処理を必要とするなら、そーいったライブラリにしておけば便利かもしれませんね。 BEGIN_TABORDER_DEF(MyDialog, CDialog) DEF_TABORDER(IDC_XXX1) DEF_TABORDER(IDC_XXX2) DEF_TABORDER(IDC_XXX3) DEF_TABORDER(IDC_XXX4) DEF_TABORDER(IDC_XXX5) END_TABORDER_DEF() みたいな^^

kawamu
質問者

お礼

回答をしていただき有難うございます。 また,返事が遅れてしまいすみませんでした。 文字数制限の為,質問本文にはかけませんでしたが,SetWindowPosで ZORDERを変更することで,タブオーダーの順番を変えようとしたの ですが,SetWindowPosの戻り値はTRUEにもかかわらずタブオーダーの 順番は変わりませんでした. (ページ内,ダイアログ内のタブオーダーの変更はできましたが, タブのタブオーダーは変更できませんでした.) その為,PretranslateMessageを使用してTABキー押下イベントを 横取りして,無理やりフォーカスが移動するコントロールを変更する 方法をとりました. スマートな方法というか(すみません,書き方が悪かったです), MFCで用意されている関数を使用して,もう少し簡単にできない かな~と思っています.

kawamu
質問者

補足

これ以上他の回答もなさそうなので締め切ろうと思います. 結局SetWindowPos等を使用してのタブオーダーの変更は できなかったためPretranslateMessageを使用することにしました. 有難う御座いました.

関連するQ&A

  • プロパティーシートのHELPボタンの非表示について

    プロパティーシートのHELPボタンの非表示にするために以下のようなソースを記述しましたが、うまくいきませんでした。なにかまちがっているのでしょうか?教えてください。 CDUserSheet::CDUserSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(nIDCaption, pParentWnd, iSelectPage) { m_psh.dwFlags &= ~(PSH_HASHELP); m_psh.dwFlags |= PSH_NOAPPLYNOW; // 画面表示 AddPage(&m_Y_UserPage1); AddPage(&m_Y_UserPage2); AddPage(&m_Y_UserPage3); }

  • ダイアログのOKボタンを押してウィンドウを生成する方法は?

    ダイアログのOKボタンを押すとウィンドウが生成する方法を教えてください。 MFCでプログラミングしてメインウィンドウをダイアロボックスにしています //アプリケーション class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; //メインダイアログ class CMyDlg : public CDialog { public: CMyDlg(CWnd *pParentWnd=NULL); protected: virtual void OnOK(); virtual void OnCancel(); }; #include <afxwin.h> #include <afxdlgs.h> #include <string.h> #include "dlg.h" #include "resource.h" CMyApp myApp; BOOL CMyApp::InitInstance(){ m_pMainWnd = new CMyDlg; m_pMainWnd ->ShowWindow(m_nCmdShow); m_pMainWnd ->UpdateWindow(); return TRUE; } CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) { Create("MYDLG"); } としています。 ダイアログはできるのですが、ここからウィンドウを生成する方法を教えてください

  • メインダイアログのデータをウィンドウに反映させたい

    メインダイアログからウィンドウを生成しています ダイアログの値を GetDlgItemText()関数で取るまではいいのですが それから、値をウィンドウに反映できません。 メンバ値を遣うと思うのですが、どうすればいいのでしょうか? プログラムを添付します ///////////////////////////////////////////////////////// // dlg.rc #include "resource.h" #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 134, 80 STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "ダイアログからウィンドウ" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,15,55,50,14 PUSHBUTTON "キャンセル",IDCANCEL,65,55,50,14 EDITTEXT IDC_EDIT1,15,10,100,35,ES_AUTOHSCROLL END ////////////////////////////////////////////////// // resource.h #define IDC_EDIT1 1000 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif //////////////////////////////////////////////////////// // dlg.h //アプリケーション class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; //ウィンドウ class CMyWindow : public CFrameWnd { private: CString MyMainStr; protected: afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() }; //メインダイアログ class CMyDlg : public CDialog { public: CString m_MyStr; CMyDlg(CWnd *pParentWnd=NULL); CMyWindow* m_pMyWnd; protected: virtual void OnOK(); virtual void OnCancel(); }; ///////////////////////////////////////////// // DlgWnd.cpp #include <afxwin.h> #include <afxdlgs.h> #include <string.h> #include "dlg.h" #include "resource.h" CMyApp myApp; BOOL CMyApp::InitInstance(){ m_pMainWnd = new CMyDlg; m_pMainWnd ->ShowWindow(m_nCmdShow); m_pMainWnd ->UpdateWindow(); return TRUE; } CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/):m_pMyWnd(NULL) //イニシャライザでポインタをNULLに初期化 { Create("MYDLG"); } BEGIN_MESSAGE_MAP(CMyWindow, CFrameWnd) ON_WM_PAINT() END_MESSAGE_MAP() void CMyDlg::OnOK() { GetDlgItemText(IDC_EDIT1, m_MyStr); const RECT rc = {10, 10, 320, 240}; m_pMyWnd = new CMyWindow(); m_pMyWnd->Create( NULL, "ダイアログから起動", WS_OVERLAPPEDWINDOW, rc, this,NULL); m_pMyWnd->ShowWindow(SW_SHOW); } void CMyDlg::OnCancel() { DestroyWindow(); } void CMyWindow::OnPaint() { CPaintDC dc(this); CMyDlg dlg; MyMainStr = dlg.m_MyStr; dc.TextOut(0, 0, MyMainStr); } よろしく御願いします

  • CFromViewの OnDrawメソッドについて

    MFC初心者です。VC2005でグラフィックスに挑戦しております。 まだよくクラスとか、MFCの作法などしらないのでトンチンカンな質問をしますが、 ドキュメント(で正しいでしょうか?)がCViewクラスの場合、 OnDraw(CDC* pDC)が定義されていたので、直接そこに描画コードを書きましたが、 CFromViewクラス(コントロール可能)の場合、 OnDraw(CDC* pDC)が見当たりませんので、定義にvoid OnDraw(CDC* pDC)を追加し、 以下のようにメソッドを追加して、無理やり表示させました。 この方法は普通でしょうか? void CtestView::OnDraw(CDC* pDC) { CBrush myBrush; CBrush* pOldBrush; myBrush.CreateSolidBrush(RGB(255,0,0)); // ソリッドブラシの作成 pOldBrush = pDC->SelectObject(&myBrush); // myBrushを選択 pDC->Ellipse(60,10,160,110); pDC->SelectObject(pOldBrush); // 元に戻す myBrush.DeleteObject(); // ブラシを削除 } //--------------------------------------------------- 以下クラス定義部 class CtestView : public CFormView { protected: // シリアル化からのみ作成します。 CtestView(); DECLARE_DYNCREATE(CtestView) public: enum{ IDD = IDD_test_FORM }; // 属性 public: CtestDoc* GetDocument() const; // 操作 public: // オーバーライド public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート virtual void OnInitialUpdate(); // 構築後に初めて呼び出されます。 // 実装 public: virtual ~CtestView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif void OnDraw(CDC* pDC); /////////////////////////// ←勝手に追加 protected: // 生成された、メッセージ割り当て関数 protected: DECLARE_MESSAGE_MAP() }; #ifndef _DEBUG // testView.cpp のデバッグ バージョン inline CtestDoc* CtestView::GetDocument() const { return reinterpret_cast<CtestDoc*>(m_pDocument); } #endif

  • 別スレッドからメインダイアログのコントロールにアクセスする方法

    VC++2005 MFC WindowsXPを使用しています。 メインダイアログに作成したエディットボックスに フォーカスをセットしたいのですが、 別スレッドから行うにはどのようにすればよいのでしょうか? メインダイアログにあるボタンを押すと別スレッドの処理に入り、 その中でメインダイアログのコントロールを操作しようとしています。 //フォーカスをセット CWnd* MyEdit = ( CWnd* )this->GetDlgItem( IDC_EDIT1 ); MyEdit->SetFocus(); 宜しくお願い致します。

  • 非表示のメインウィンドウを表示させるには?

    環境 WIN98 VC++6.0 MFC SDIにて タスクトレイに常駐するアプリにおいて 1.起動時にメインウィンドウを非表示にしています。 2.起動時と同時にダイアログを表示しています。 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { 略 dlg = new CInput(this); dlg->Create(IDD_DIALOG1); dlg->ShowWindow(SW_SHOW); return 0; } 3.このような場合に、ダイアログのボタン押し下げにて、メインウィンドウを表示させるには、どうすれば良いでしょうか? 以下のようにしてみましたが、不正な処理で落ちてしまいます。 void CInput::OnButton1() { CWnd* mywnd = (CWnd*)GetParent(); mywnd->ShowWindow(SW_SHOW); }

  • Cwndクラスの派生クラスmCWndクラスのOnDrawについて

    OnDraw関数が呼び出しされていません。 どうすればいいですか? よろしくお願いします。 class mCWnd :public CWnd { public: DECLARE_MESSAGE_MAP() afx_msg void OnLButtonDown(UINT nFlags,CPoint point) { AfxMessageBox("子ウインドウ"); CDC *pDC=GetDC(); pDC->TextOut(0,0,"HELLO"); ReleaseDC(pDC); Invalidate(); } virtual void OnDraw(CDC* pDC) { AfxMessageBox("OnDraw"); pDC->FillSolidRect(CRect(0,0,300,300),RGB(255,255,255)); } }; BEGIN_MESSAGE_MAP(mCWnd, CWnd) ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() ------------------------------------------- //***View.cpp (mCWnd cw) void CKoDlg::OnBnClickedButton1() { CRect rect=CRect(50,50,190,250); cw.Create(NULL,"Hello",WS_CHILD|WS_VISIBLE,rect,this,5000,0); // TODO : ここにコントロール通知ハンドラ コードを追加します。 }

  • [Visual C++ 6.0] コンパイル(ビルド)エラー

    ※参考までに『3週間完全マスターVisual C++ 6.0 』という本の「5日目」の部分を進めていて詰まってしまいました。 ビルドすると、下記のDialogsDlg.h中の「CMsgDlg m_dMsgDlg;」の辺りに対して error C2146: 構文エラー : ';' が、識別子 'm_dMsgDlg' の前に必要です。 error C2501: 'CMsgDlg' : 識別名を宣言するのに、型が指定されていません。 error C2501: 'm_dMsgDlg' : 識別名を宣言するのに、型が指定されていません。 というエラーが出てしまいます。CMsgDlgというクラスはちゃんと作っていますし、構文的にも間違ってはいないと思うのですが、何がいけないのでしょうか? 説明が足りなければ補足します(見づらくてスミマセン)。 // DialogsDlg.h : #if !defined(AFX_DIALOGSDLG_H__4772C7E5_F2C9_4E57_99B8_EF1D44426473__INCLUDED_) #define AFX_DIALOGSDLG_H__4772C7E5_F2C9_4E57_99B8_EF1D44426473__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif class CDialogsDlg : public CDialog { public: CDialogsDlg(CWnd* pParent = NULL); enum { IDD = IDD_DIALOGS_DIALOG }; CButton m_cWhichOption; CString m_sResults; protected: virtual void DoDataExchange(CDataExchange* pDX); protected: HICON m_hIcon; //{{AFX_MSG(CDialogsDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnExit(); afx_msg void OnYesnocancel(); afx_msg void OnAbortretryignore(); afx_msg void OnFileopen(); afx_msg void OnBcustomdialog(); afx_msg void OnBwhichoption(); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: CMsgDlg m_dMsgDlg; }; #endif

  • 新ダイアログの初期化

    DoModalなどで新ダイアログを呼び出しているのですが その新ダイアログの初期設定ができません。例えばリストビューなどで m_list.InsertColumn(0,"名前",LVCFMT_CENTER,100); などをしたいのですが 新ダイアログのクラス:NewClass #include ・ ・ ・ #endif CNewClass::CNewClass(CWnd* pParent) : CDaialog(CNewClass::IDD,pParent) { } void CNewClass::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(・・) ・ ・ END_MESSAGE_MAP() がかかれているんですがどこに書けばいいんでしょうか? 一番上の関数だと思ってそこに書いたらDebug AssertionFailed! とでます。そのInsertColumnを入れなければエラーはでません。 ということは入れる場所に問題があるのかとおもいました。 解決方法を教えて下さい。

  • ダイアログボックスのボタンコントロールのフォーカスについて

    ダイアログボックスのボタンコントロールのフォーカスについて 教えて下さい。  モーダルダイアログにボタン「OK」を一つ貼り付けて それを「標準のボタン」(BS_DEFPUSHBUTTON)として作成したのですが ダイアログ表示直後は下画像(1)のようになってエンターキーを押しても 反応しません。何度かカーソルキーを押すとようやく(2)のように ボタンに枠線がついてエンターで押せるようになるのですが ダイアログ表示直後に(2)のようにするにはどうするべきでしょうか? ダイアログのコールバック・プロシージャ(WM_INITDIALOG部分でボタン作成) LRESULT CALLBACK SettingWndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ switch (msg){ case WM_INITDIALOG: CreateWindowEx(0x00000000,"BUTTON","OK", WS_CHILD |WS_VISIBLE| WS_TABSTOP | BS_DEFPUSHBUTTON, 16,16,80,21,hWnd,(HMENU)IDOK,GetModuleHandle(0),0); return TRUE; } return FALSE; }

専門家に質問してみよう