SDIで包含関係のない子ウインドウを作りたい – 固定ページ 2 – プログラミング – Home

SDIで包含関係のない子ウインドウを作...
 
通知
すべてクリア

[解決済] SDIで包含関係のない子ウインドウを作りたい

固定ページ 2 / 2

yasuda
 yasuda
(@yasuda)
ゲスト
結合: 16年前
投稿: 24
Topic starter  

どうも、ご返事ありがとうございます。

いろいろ調べたのですが、あまりよくわからないので、苦し紛れにメインウインドウの
OnDraw のところに、別ウインドウの再描画コードを書きました。

自分でもわかっているのですが、別ウインドウが、親ウインドウに乗っかったり、すこ
しでも引っかかっているときは、親ウインドウの OnDraw が発生するので、別ウインド
ウも再描画されますが、

親ウインドウと、別ウインドウを左右に独立にデスクトップで配置して、別ウインドウ
のサイズをマウスで変更させたりして再描画要求をだしても、下記の
another_window_draw() というコードは、親ウインドウのOnDraw経由なので、当然なが
ら実行されません。

このような場合、どのようにして別ウインドウで発生したメッセージを捉えればよいの
でしょうか?ご存知の方がいらっしゃいましたら、ご教示お願いいたします。

int another_window_draw( CWnd* wnd, COLORREF c_brsh, COLORREF c_pen )
{

HWND hwnd = wnd->GetSafeHwnd();

RECT rct;
::GetClientRect( hwnd, &rct );
int cw = rct.right - rct.left;
int ch = rct.bottom - rct.top;

HDC hdc_wnd = ::GetDC( hwnd );

HDC hdc_bak = ::CreateCompatibleDC( hdc_wnd );
HBITMAP hbmp_bak = ::CreateCompatibleBitmap( hdc_wnd, cw, ch );
::SelectObject( hdc_bak, hbmp_bak );

HBRUSH brsh = ::CreateSolidBrush( c_brsh );
::FillRect( hdc_bak, &rct, brsh );
::DeleteObject( brsh );

int pen_width = 4;
HPEN pen = ::CreatePen( PS_SOLID, pen_width, c_pen );
::SelectObject( hdc_bak, pen );
::MoveToEx( hdc_bak, 0, 0, NULL );
::LineTo( hdc_bak, cw, ch );
::MoveToEx( hdc_bak, cw, 0, NULL );
::LineTo( hdc_bak, 0, ch );
::DeleteObject( pen );

::BitBlt( hdc_wnd, 0, 0, cw, ch, hdc_bak, 0, 0, SRCCOPY );

::DeleteDC( hdc_bak );
::DeleteObject( hbmp_bak );

::ReleaseDC( hwnd, hdc_wnd );

return 0;

}

void CaaaView::OnDraw(CDC* /*pDC*/)
{
CaaaDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

// TODO: この場所にネイティブ データ用の描画コードを追加します。
HWND hwnd = this->GetSafeHwnd();

RECT rct;
::GetClientRect( hwnd, &rct );
int cw = rct.right - rct.left;
int ch = rct.bottom - rct.top;

HDC hdc_wnd = ::GetDC( hwnd );

HDC hdc_bak = ::CreateCompatibleDC( hdc_wnd );
HBITMAP hbmp_bak = ::CreateCompatibleBitmap( hdc_wnd, cw, ch );
::SelectObject( hdc_bak, hbmp_bak );

HBRUSH brsh = ::CreateSolidBrush( RGB( 0x00, 0x00, 0xff ) );
::FillRect( hdc_bak, &rct, brsh );
::DeleteObject( brsh );

int pen_width = 4;
HPEN pen = ::CreatePen( PS_SOLID, pen_width, RGB( 0x00, 0xff,
0x00 ) );
::SelectObject( hdc_bak, pen );
::MoveToEx( hdc_bak, 0, 0, NULL );
::LineTo( hdc_bak, cw, ch );
::MoveToEx( hdc_bak, cw, 0, NULL );
::LineTo( hdc_bak, 0, ch );
::DeleteObject( pen );

::BitBlt( hdc_wnd, 0, 0, cw, ch, hdc_bak, 0, 0, SRCCOPY );

::DeleteDC( hdc_bak );
::DeleteObject( hbmp_bak );

::ReleaseDC( hwnd, hdc_wnd );

// 別のウインドウを再描画する.
another_window_draw( MyWnd, RGB( 0x00, 0xff, 0xff ), RGB( 0xff, 0x00,
0xff ) );

}

BOOL CaaaView::OnEraseBkgnd(CDC* pDC)
{
// TODO : ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼
び出します。
return TRUE;
}


返信引用
yasuda
 yasuda
(@yasuda)
ゲスト
結合: 16年前
投稿: 24
Topic starter  

すいません、みずから困難な方向に進んでいっていたのかもしれません。
上級者の皆様がハタメからみたら、こいつなんでこっちにいってるんだろう?と疑問だ
ったかもしれません。(恥ずかしい...)

rin さんのご指摘の、モードレスな CDialog というのを試してみました。
なかなかうまくいきました。

すいませんが、CDialog にスクロールバーをつけるのは、どうすればよいでしょうか。
モードレスダイアログの Createのときに、スクロールバーがつけられたり、ウインドウ
サイズを変更できる、ウインドウスタイルを決定する引数をつければよいのでしょう
か。

Dlg00 = new CDialogAnother();
Dlg00->Create( IDD_DIALOG_ANOTHER, m_pMainWnd );
Dlg00->ShowWindow( SW_SHOW );

サイズが変更できるようになったら、今度はティアリングの回避について悩みそうで怖
い...

class CDialogAnother : public CDialog
{
// この中、カキコのため色々省略してます。
CDialogAnother(CWnd* pParent = NULL); // 標準コンストラクタ
virtual ~CDialogAnother();
enum { IDD = IDD_DIALOG_ANOTHER };
afx_msg void OnPaint();
};

void CDialogAnother::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO : ここにメッセージ ハンドラ コードを追加します。
// 描画メッセージで CDialog::OnPaint() を呼び出さないでください。

HWND hwnd = this->GetSafeHwnd();

RECT rct;
::GetClientRect( hwnd, &rct );
int cw = rct.right - rct.left;
int ch = rct.bottom - rct.top;

HDC hdc_wnd = ::GetDC( hwnd );

HDC hdc_bak = ::CreateCompatibleDC( hdc_wnd );
HBITMAP hbmp_bak = ::CreateCompatibleBitmap( hdc_wnd, cw, ch );
::SelectObject( hdc_bak, hbmp_bak );

COLORREF c_brsh = RGB( 0xff, 0x00, 0xff );
HBRUSH brsh = ::CreateSolidBrush( c_brsh );
::FillRect( hdc_bak, &rct, brsh );
::DeleteObject( brsh );

int pen_width = 4;
COLORREF c_pen = RGB( 0xff, 0xff, 0x00 );
HPEN pen = ::CreatePen( PS_SOLID, pen_width, c_pen );
::SelectObject( hdc_bak, pen );
::MoveToEx( hdc_bak, 0, 0, NULL );
::LineTo( hdc_bak, cw, ch );
::MoveToEx( hdc_bak, cw, 0, NULL );
::LineTo( hdc_bak, 0, ch );
::DeleteObject( pen );

::BitBlt( hdc_wnd, 0, 0, cw, ch, hdc_bak, 0, 0, SRCCOPY );

::DeleteDC( hdc_bak );
::DeleteObject( hbmp_bak );

::ReleaseDC( hwnd, hdc_wnd );

}


返信引用
rin
 rin
(@rin)
ゲスト
結合: 18年前
投稿: 112
 

>このような場合、どのようにして別ウインドウで発生したメッセージを捉えればよいの
>でしょうか?ご存知の方がいらっしゃいましたら、ご教示お願いいたします。
この方法のまま進めたいのでしょうか?

メインウィンドウは、CViewの派生だからOnDraw()だけど
別ウィンドウクラスは、CWndだからWM_PAINT(OnPaint)でいい

http://msdn.microsoft.com/ja-jp/library/01c9aaty(VS.80).aspx

今回の場合ですが、たぶん・・・

A:まず、別ウィンドウ用に、独自の「CWndの派生クラス」を作成します
(メニュー「プロジェクト」>「クラスの追加」>MFC選択・・・)

B:親ウィンドウには、その独自クラスでメンバ変数を登録

C:あとは、その独自クラスに対し(クラスビューに追加されてるので楽)、
OnPaintなどを追加し、そこにコードを書く

こんな感じで。

オリジナルの動作をさせたいときは、「クラスの派生」をさせるのが筋。


返信引用
yasuda
 yasuda
(@yasuda)
ゲスト
結合: 16年前
投稿: 24
Topic starter  

で、できました!うれしい。
rinさんをはじめ皆様ありがとうございました。

rinさんに教えていただいた方法でクラスの追加をして、クラスビューでいろいろ処理す
るメッセージを追加していくという方法にしました。
(CDialogで日常的にやっている方法だったのになぜ気づかなかったのだろうか)

とりあえず上級者の皆様には、私の紆余曲折にツッコミどころ満載でしょうから、解決
チェックボックスは週明け数日間は入れないでおくことにします。

class CaaaView : public CScrollView
{
// カキコ用にいろいろ省略.
public:
CWndAnother* Wnd00;

// カキコ用にいろいろ省略.

};

CaaaView::CaaaView()
{
// TODO: 構築コードをここに追加します。

WNDCLASS Wc;
memset(&Wc, NULL, sizeof(WNDCLASS));
Wc.lpfnWndProc = AfxWndProc;
Wc.hInstance = AfxGetInstanceHandle();
Wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
Wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
Wc.lpszClassName = _T(Class);
Wc.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
Wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
AfxRegisterClass(&Wc);

Wnd00 = new CWndAnother();
Wnd00->CreateEx(
WS_EX_TOPMOST,
Wc.lpszClassName,
_T( Window ),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CRect(8, 8, 320, 240),
this,
0
);

}

BOOL CWndAnother::OnEraseBkgnd(CDC* pDC)
{
// ティアリング対策.
return TRUE;
}

void CWndAnother::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO : ここにメッセージ ハンドラ コードを追加します。
// 描画メッセージで CWnd::OnPaint() を呼び出さないでください。

HWND hwnd = this->GetSafeHwnd();

RECT rct;
::GetClientRect( hwnd, &rct );
int cw = rct.right - rct.left;
int ch = rct.bottom - rct.top;

HDC hdc_wnd = ::GetDC( hwnd );

HDC hdc_bak = ::CreateCompatibleDC( hdc_wnd );
HBITMAP hbmp_bak = ::CreateCompatibleBitmap( hdc_wnd, cw, ch );
::SelectObject( hdc_bak, hbmp_bak );

COLORREF c_brsh = RGB( 0xff, 0x00, 0xff );
HBRUSH brsh = ::CreateSolidBrush( c_brsh );
::FillRect( hdc_bak, &rct, brsh );
::DeleteObject( brsh );

int pen_width = 4;
COLORREF c_pen = RGB( 0xff, 0xff, 0x00 );
HPEN pen = ::CreatePen( PS_SOLID, pen_width, c_pen );
::SelectObject( hdc_bak, pen );
::MoveToEx( hdc_bak, 0, 0, NULL );
::LineTo( hdc_bak, cw, ch );
::MoveToEx( hdc_bak, cw, 0, NULL );
::LineTo( hdc_bak, 0, ch );
::DeleteObject( pen );

::BitBlt( hdc_wnd, 0, 0, cw, ch, hdc_bak, 0, 0, SRCCOPY );

::DeleteDC( hdc_bak );
::DeleteObject( hbmp_bak );

::ReleaseDC( hwnd, hdc_wnd );

}


返信引用
yasuda
 yasuda
(@yasuda)
ゲスト
結合: 16年前
投稿: 24
Topic starter  

aetosさん wclrpさん bunさん 仲澤さん デゴルガンさん とおりすがりさん rinさん

ありがとうございました。


返信引用
固定ページ 2 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました