MDIの子ウインドウに描画するには?


トール  2004-12-04 03:41:00  No: 55442

始めまして。
C言語(WIN32API)を使用してペイントソフトを作っているものです。

さっそくですが、MDIで子ウインドウを作成して線を描けるようにしたいのですが、二つ以上ウインドウをだしてしまうと上の子ウインドウに描いた線が
下の子ウインドウにまったく同じようにコピーされてしまいます。

なにかいい方法はないでしょうか?
よろしくお願いします。
環境は  Visual Stadio.netです。


なーめ  2004-12-04 20:38:09  No: 55443

この質問文ではレスのつけようがないと
指摘されそうですよ。

>> C言語(WIN32API)を使用
>> MDIで子ウインドウ
おそらく、MFC/Appwizard からですね。

Debugモードで。
描画しているところ(CView 派生クラスOnDraw()等)に
TRACE("ここに関数名を書く");
を入れてみるとよい。
コピーされているのか、2度実行されているのかが、
区別つくよ。
また、このマクロのところにブレークポイントを置いて
コールスタックをさかのぼると
どこから呼ばれているのかがわかるので、
2度呼ばれているとしたら、
そうならないように、制御すべき部分が特定できるはず。


トール  2004-12-04 21:42:33  No: 55444

レスありがとうございます。
質問の仕方が悪かったようですいませんでした。

C言語(WIN232API)といのはWINDOWSプログラミング?(猫でもわかるのサイトの方ではWINDOWS SDK)
と表記されてました。

CreateMDIWindowを使用して子ウインドウを作成しました。
その後、CreateCompatibleBitmapを使用しビットマップを作り線を描こうと思っています。

しかし、線を描くというところまではできたのですが、アクティブなっているウインドウに線を描くと、
非アクティブになっているウインドウにまで線が描かれてしまいます。

EnumChildWindowsを使用すればいいのかなと思うのですが、実現方法がわかりまん。

足りないことがあるかもしれませんが、よろしくお願いします。


なーめ  2004-12-05 05:36:10  No: 55445

じゃあ、
TRACE()が使えないから、
OutoutDebugString("XXXXX;\n");
でやってみて。
なお、この関数はprintf系書式は使えません。
---
一方この現象だけど、各子ウィンドウに独立したデータを保持して
いないのではないかな。
共通のデータを元に、同じ描画が行なわれれば、コピーしたように見えるよね。
それとも、描画のイベントが全ての子ウィンドウに配信されているのか。
にしても、ソースがなけりゃ何もわからないですね。


トール  2004-12-13 03:40:30  No: 55446

なーめさんレスありがとうございます。
遅くなってすいません。

独立したデータを保持ということを調べていたのですが、
参考になりそうなものが見つからなかったため再度よろしくお願いします。

長くなるかもしれませんがソースの一部を乗せておきます。
hBufferとhBitmapがグローバル変数でその他はローカル変数です。

/*************************************************
*
*          フレームウインドウの処理
*
**************************************************/
case WM_CREATE:
        ccsClient.hWindowMenu = GetSubMenu(GetMenu(hWnd) , 1);
        ccsClient.idFirstChild = ID_CHILDWND;

        hClient = CreateWindow("MDICLIENT" , NULL ,
    WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE ,
    0 , 0 , 0 , 0 ,
    hWnd , (HMENU)1 , hIns ,&ccsClient
        );
  break;
case WM_COMMAND:
        switch(LOWORD(wParam)) {
      case ID_MNU_new:
    hChild = CreateMDIWindow(MDI_CHILD , szFile , 0 ,
      CW_USEDEFAULT , CW_USEDEFAULT ,
      CW_USEDEFAULT , CW_USEDEFAULT ,
      hClient , hIns , 0
    );

    GetClientRect(hChild,&win);
    hdc = GetDC(hChild);
    hBitmap = CreateCompatibleBitmap(hdc,win.right,win.bottom);
    hBuffer = CreateCompatibleDC(hdc);
    SelectObject(hBuffer,hBitmap);
    PatBlt(hBuffer , 0 , 0 ,win.right,win.bottom, WHITENESS);
    ReleaseDC(hChild,hdc);
    break;
           }
/*********************************************
*
*         クライアントウインドウの処理
*
**********************************************/
switch(uMsg){
case WM_CREATE:
     hClient = GetParent(hWnd);
     hFrame = GetParent(hClient);
     break;
case WM_LBUTTONDOWN:
    click = true;
    rc.left = LOWORD(lParam);
    rc.top = HIWORD(lParam);
    SetCapture(hWnd);
    break;
    case WM_LBUTTONUP:
    hChild = (HWND)SendMessage(hClient , WM_MDIGETACTIVE , 0 , 0);
    if(click){
  click = false;
  rc.right = LOWORD(lParam);
  rc.bottom = HIWORD(lParam);
  InvalidateRect(hChild , NULL ,true);
  ReleaseCapture();
    }  
    break;
case WM_MOUSEMOVE:
    hChild = (HWND)SendMessage(hClient , WM_MDIGETACTIVE , 0 , 0);
    if(click){
  hdc = BeginPaint(hChild,&ps);
  rc.right = rc.left;
  rc.bottom = rc.top;
  rc.left = LOWORD(lParam);
  rc.top = HIWORD(lParam);
  if(rc.left>5000){
    rc.left -= 65536;
  }
  if(rc.top>5000){
          rc.top -= 65536;
  }
  SetPixel(hBuffer,rc.left,rc.top,RGB(0,0,0));
  MoveToEx(hBuffer,rc.left,rc.top,NULL);
  LineTo(hBuffer,rc.right,rc.bottom);
  InvalidateRect(hChild , NULL , false);
  EndPaint(hChild,&ps);
    }
    break; 
    case WM_PAINT:
        hChild = (HWND)SendMessage(hClient, WM_MDIGETACTIVE , 0 , 0);

  GetClientRect(hChild,&win);
  hdc = BeginPaint(hChild,&ps);
  BitBlt(hdc,0,0,win.right,win.bottom,hBuffer,0,0,SRCCOPY);
  EndPaint(hChild,&ps);
  break;
}


なーめ  2004-12-13 10:29:45  No: 55447

>> クライアントウインドウの処理
MDI子ウィンドウじゃないの?

>> 独立したデータを保持ということを調べていたのですが、
>> 参考になりそうなものが見つからなかったため再度よろしくお願いします。

case WM_PAINT:
  hChild = (HWND)SendMessage(hClient, WM_MDIGETACTIVE , 0 , 0);
  GetClientRect(hChild,&win);
  hdc = BeginPaint(hChild,&ps);
  BitBlt(hdc,0,0,win.right,win.bottom,hBuffer,0,0,SRCCOPY);
  EndPaint(hChild,&ps);
  break;

問題はこれですね。
子ウィンドウ1と子ウィンドウ2で同じ描画データ hBuffer を
共有しているように見えますね。

case WM_COMMAND:
  switch(LOWORD(wParam)) {
    case ID_MNU_new:
      hChild = CreateMDIWindow(MDI_CHILD , szFile , 0 ,
        CW_USEDEFAULT , CW_USEDEFAULT ,
        CW_USEDEFAULT , CW_USEDEFAULT ,
        hClient , hIns , 0
      );
      GetClientRect(hChild,&win);
      hdc = GetDC(hChild);
      hBitmap = CreateCompatibleBitmap(hdc,win.right,win.bottom);
      hBuffer = CreateCompatibleDC(hdc);
      SelectObject(hBuffer,hBitmap);
      PatBlt(hBuffer , 0 , 0 ,win.right,win.bottom, WHITENESS);
      ReleaseDC(hChild,hdc);
      break;
  }

2つめの子ウィンドウを作成したときには
2つめの hBitmap, hBuffer も作成しなければなりませんね。
で、それは出来ているようです。
しかし、そのハンドルは子ウィンドウ1のハンドルに上書き
しているみたいですよ。

独立していない、とはそういうことです。

ではどのようにして、いくつ生成されるか分からない子ウィンドウと
そのデータを管理するか。
C++ ですからね。ここはちょっと考えてください。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加