• ベストアンサー

非クライアント領域への描画について

非クライアント領域に文字を書こうとしました。 以下の(2)では書けますが、(1)では書いてくれません。 CPaintDCはクライアント領域でないとダメなのですか? void CMainFrame::OnPaint() { CPaintDC dc(this); // 描画用のデバイス コンテキスト dc.TextOut(0,0,"こんにちは"); ・・・(1) CDC* pDC = GetWindowDC(); pDC->TextOut(100,0,"こんにちは"); ・・・(2) 環境 WIN98 VC++6.0 MFC

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

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>以下の(2)では書けますが、(1)では書いてくれません。 というか、(1)はクライアント領域に描画されますよね? >CPaintDCはクライアント領域でないとダメなのですか? だめです。 http://www.microsoft.com/JAPAN/developer/library/vcmfc/_mfc_cpaintdc.htm >CPaintDC クラスは、CDC クラスから派生したデバイス コンテキスト クラスです。構築時に CWnd::BeginPaint 関数を実行し、消滅時に CWnd::EndPaint 関数を実行します。 > >CPaintDC オブジェクトは、WM_PAINT メッセージに応答するときのみ使います。通常は OnPaint メッセージ処理メンバ関数で使います。 WM_PAINTが送られてきたときにBeginPaintを呼んで得られる デバイスコンテキストは、クライアント領域ですよね。 これで非クライアント領域まで描画できるとすると、 通常のクライアント領域の描画がとても大変になってしまいますよね。

VitaminBB
質問者

お礼

回答ありがとうございます。 >というか、(1)はクライアント領域に描画されますよね? そう思ったのですが、クライアント領域にも描画されません。 もちろん、void CXxxView::OnPaint()内なら描画されます。

その他の回答 (4)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.5

おまけ http://www.okweb.jp/kotaeru.php3?q=825118 ここで、Viewのメンバ変数の値を子ウィンドウから見ようとしていましたよね。 で、解決方法が、 1.親ウィンドウのCViewを取得する 2.親ウィンドウをCViewにする の2つの方法が回答されています。 こうしなければいけない理由が、 1.CDialogのコンストラクタで親ウィンドウを指定しなかった場合は、アプリケーションのメインウィンドウ(フレーム)となっているから。 2.フレームとビューのウィンドウは別だから。 ということなのです。 ここでの理由をしっかり考えていただければ今回の質問は出てこなかったかな?

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.4

>ビュー=クライアント領域と思っていましたが、 >クライアント領域の上にビューが描かれているという >ことでしょうか? MFCのスケルトンから生成したウィンドウアプリの構造に少々誤解があるようですね。 MFCのウィンドウアプリは、ドキュメント/ビューアーキテクチャーといって、4つの主要なクラスによって成り立っていて、それぞれに別の役割を持たせています。 http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vccore/html/_core_document.2f.view_architecture_topics.asp ここで、CFrameWndとCViewが、ウィンドウの表示に関するクラスとなっていて、その関係は、CFrameWndが親ウィンドウで、CViewが子ウィンドウになっています。 他のクラスの役割についてはurlの内容を読んでください。 MFCのスケルトンでは、メニューを含めたウィンドウ全般の処理は、CFrameWndで、クライアント領域への描画はCViewとクラスを分けることで、処理を切り分けるようなつくりになっています。 このため、CFrameWndのクライアント領域は、通常はその全てをCViewのウィンドウが覆っている状態となっています。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

>CMainFrame::OnPaint() >そう思ったのですが、クライアント領域にも描画されません。 >もちろん、void CXxxView::OnPaint()内なら描画されます。 ってことは、CMainFrameにビューが張り付いてるっとことですよね。 描画対象となるクライアント領域って見えてますか? 見えてないなら描画結果も見えないと思いますけど。

VitaminBB
質問者

お礼

回答ありがとう御座います。 ビュー=クライアント領域と思っていましたが、 クライアント領域の上にビューが描かれているという ことでしょうか? ダイアログベースで試すと確かに書くことが出来ました。

回答No.1

最近、プログラムしていませんので空耳程度に、、 うーん、デスクトップ画面以外のターゲットにそれをやるとエラーになった気がします。<仮想表示エリアが無いため

VitaminBB
質問者

お礼

回答ありがとうございます。

関連するQ&A

  • クライアント領域をCBitmapに取り込みたい

    VC6.0MFCで クライアント領域(みたまま)を CBitmapに取り込みたいのですがどうすればよいのでしょうか? ためしにダイアログの領域をクリップボードに取り込むコード OnPaint書いたのですが真っ黒の画像しか取り込めていませんでした。 根本的に使うAPIが違うのでしょうか? void CCaptureDlg::OnPaint() {  CPaintDC dc(this); // 描画用のデバイス コンテキスト  CRect cr;  GetClientRect(&cr);  dc.TextOut(0,0,"テスト");  CDC* pDC = new CDC();  pDC->CreateCompatibleDC(&dc);  CBitmap img;  img.CreateCompatibleBitmap(pDC, cr.Width(), cr.Height());  OpenClipboard();  ::EmptyClipboard();  ::SetClipboardData(CF_BITMAP, img.GetSafeHandle());  ::CloseClipboard();  pDC->DeleteDC();  delete pDC;  CDialog::OnPaint(); }

  • クライアント領域のコントロールが描画されない

    WindowsXP / VC2005 / VC++ MFCにてダイヤログベースの画像ビューワの作成を行っています。 機能としては、独自形式のバイナリファイルをダイヤログへドラッグ&ドロップすることにより、 メモリに描画した画像をクライアント領域へ転送して表示します。 こちらが疑問点となるところなのですが、その際にもともと配置していた エディットボックスやスピンボタンなどのコントロールが消えてしまいます。 (見えなくてもボタンを押すことはできるので描画の問題と思われます) 1.なぜこのようなことが起こるのでしょうか? 2・また、コントロールを消さないためにはどうすればよいのでしょうか? 上記に関してご回答いただけると幸いです。 個人的な考えとしては、  1.クライアント領域を描画する際にコントロールを消してしまっている  2.再描画することによりコントロールは表示される(但し問題点としてクライアント領域を書き換える際にちらつく) です。 以下該当関数です //------------------------------------------------------------------------------ void CTestBitBltDlg::OnDropFiles(HDROP hDropInfo) { char acFileName[256]; SHORT sRet; memset(acFileName, 0, sizeof(acFileName)); DragQueryFile(hDropInfo, 0, acFileName, sizeof(acFileName)); memcpy( g_acSpriteFileName, acFileName, 256 - 1 ); CRect rc; GetClientRect(&rc); CClientDC dc(this); CDC dcMem; dcMem.CreateCompatibleDC(&dc); CBitmap bmp; bmp.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height()); CBitmap* pOldBmp = dcMem.SelectObject(&bmp); dcMem.FillSolidRect(&rc, RGB(0xC0, 0xC0, 0xC0)); // 本関数にてメインとなるメモリDCへの描画をおこなってます sRet = GetMemoryImage(g_acSpriteFileName, 0, &dcMem); if( sRet == FALSE ){ GetDefaultImage(&dcMem); } dc.BitBlt(0, 0, rc.Width(), rc.Height(), &dcMem, 0, 0, SRCCOPY); dcMem.SelectObject(pOldBmp); //InvalidateRect(FALSE); CDialog::OnDropFiles(hDropInfo); } //------------------------------------------------------------------------------ なお、OnEraseBkgnd関数においてはTRUEのみを返すようにしてます。

  • dc.TextOut(0 ,0 , *str) ;について

    環境 WIN98 VC++6.0 MFC にて パターンBはOKですが、パターンAだと不正な処理で落ちてしまいます。 どうしてなのかお教えください。 void CFffView::OnPaint() { CPaintDC dc(this); //パターンA CString* str ; str = (CString*)("999"); dc.TextOut(0 ,0 , *str) ; //パターンB CString aaa ; aaa = (CString)("999"); dc.TextOut(0 ,0 , aaa) ; }

  • クライアント領域の保存

     初歩的な質問でごめんなさい。 VC.netのMFCで、OnLButtonDownで描画の処理をしているのですが、これだと画面を最小化したりするとクライアント領域に描画していたものが消去されてしまうので、画面全体のビットマップをメモリに保存しておきOnPaint関数でブロック転送すればよいと参考書に載っているのですが、このメモリに保存してブロック転送というのがうまくできません。  BitBltを使うのはわかるのですが、どうもうまくいきません。よろしければ、恐縮ですがソースを教えていただきたいです。お願いします。

  • ウィンドウのフレームの色変更

    <環境> Win98 VC++6.0 MFC よろしくお願いします。 ダイアログのボタン押し下げにて、新規にウィンドウを作成しています。 新規に作成したウィンドウのクライアント領域の色は、 CPaintDC dc(this); // 描画用のデバイス コンテキスト CRect cr; GetClientRect( &cr); dc.FillSolidRect( cr, RGB( 250, 250, 0)); dc.DrawText( moji,cr, DT_SINGLELINE | DT_VCENTER | DT_CENTER); にて変更することが出来ました。 クライアント領域の外側にあるフレームの色も変更したいのですが、 どのようにすれば実現可能でしょうか? ご存知の方、教えてください。お願いします。

  • CreateCompatibleDCを初期化時にしたい(MFC)

    MFCでJPEG画像を表示するプログラムを OnPaint() の中に書いていたのですが・・・  : bool m_bImageMemDCInit; CImage m_Image; CBitmap *m_pImageBitmap; CDC m_ImageMemDC;  :  : void CChildView::OnPaint() {  CPaintDC dc(this);  if(!m_bImageMemDCInit){   m_bImageMemDCInit = true;   // イメージをロード   m_Image.Load("test.jpg");   m_pImageBitmap = CBitmap::FromHandle(m_Image);   m_ImageMemDC.CreateCompatibleDC(&dc);   m_ImageMemDC.SelectObject(m_pImageBitmap);  }  // 描画  dc.BitBlt(0, 0, 256, 256, &m_ImageMemDC, 0, 0, SRCCOPY); } このように、Load や CreateCompatibleDC などの初期化にあたる処理を、起動時に1度しか処理しないように書いています。 しかし、このプログラムではあまりに汚い。どうにかして PreCreateWindow などの初期化関数内に書きたいのですが、CreateCompatibleDC 関数で CPaintDC* を渡す必要があるので、OnPaint 関数内に書かざるを得ないのです。 (Loadだけなら初期化関数内に移せるのですが・・・) いっそ CreateCompatibleDC を再描画のたびに呼んでもいいのでは? と思い、やってみると異常終了してしまいました。 また、CPaintDC dc(this); を PreCreateWindow 関数内に書いても異常終了しました。 どなたかスマートな方法をご存知でしたら、ご指導願います m(_ _)m

  • クライアント領域を再描画させない方法

    クライアント領域で左クリックを押したままマウスを移動させた時の処理 (WM_MOUSMOVE)として、マウスの位置情報を、 InvalidateRect(hWnd, NULL, FALSE); でWM_PAINTに送り、WM_PAINTで描画処理をさせます。 右クリックでの処理として、 case WM_RBUTTONDOWN:    InvalidateRect(NULL, NULL, TRUE);    return 0; とした時、WM_PAINTでは 右クリックによるWM_PAINTでは、クライアント領域を 再描画させない様にしたいのですが、 どのようにしたら良いのでしょうか? クライアント領域に描画されたのを再描画させないことで、 消したいのです。 MS VC++ & Win98 の環境で作成しています。

  • VC++2010 で線形の描画についてですが・・

    VC++2010 で線形の描画についてまた質問なんですが、以下のように記述すると線ができなく、 点だけが動くプログラムになりました。解決方法がわからないのでよろしくお願いします。 今回のプロジェクトの目的はある機器からデータを取ってきて(1msごとに)それを1msごとに 直線として出力するプロジェクトです 電圧                    ↑          ________ ↑         |          |________→→ ーーーーーーーー  →→時間 ↑↑↑ このような線を出力しなければならないです。 以下がソースになっています。 使用環境VC++2010 MFC test10000Dlg.cpp ちなみにm_lineXとm_lineYはメンバー変数です(double型) ボタンがクリックされたときのイベント SetTimer(0, 1, NULL); void Ctest10000Dlg::OnTimer(UINT_PTR nIDEvent) { UpdateData(); after_datay = sam_data; m_xvEditX = m_lineX; m_xvEditSamd = m_lineY; m_xvEditSami = sam_i++; if(sam_i%200==0) { m_lineY -= 5; sam_i = 0; } m_lineX++; UpdateWindow(); Invalidate(FALSE); } void Ctest10000Dlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 描画のデバイス コンテキスト SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // クライアントの四角形領域内の中央 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // アイコンの描画 dc.DrawIcon(x, y, m_hIcon); } else { //****************************************************************************************************** CRect rect_dlg; GetClientRect(&rect_dlg); CBrush br_black(RGB(0,0,0)); //各色ペン CPen pen_black(PS_SOLID,1,RGB(0,0,0)); CPen pen_gray(PS_DOT,1,RGB(128,128,128)); CPen pen_blue(PS_SOLID,1,RGB(0,0,255)); CPen pen_white(PS_SOLID,1,RGB(255,255,255)); int max_y=1; if(int(m_sin+m_cos+1.0)>max_y) max_y=int(m_sin+m_cos)+1; CDC* pDC=m_pict.GetDC(); //PictureControlの大きさ取得 CRect rect; m_pict.GetClientRect(&rect); //元のブラシをoldbrに保持 CBrush* oldbr=pDC->SelectObject(&br_black); //元のペンをoldpenに保持 CPen* oldpen=pDC->SelectObject(&pen_black); //(1)背景描画(ブラシ白、ペン黒) pDC->Rectangle(&rect); //(2)中心線(黒、実線) pDC->SelectObject(&pen_blue); pDC->MoveTo(10,rect.Height()-10); pDC->LineTo(10,10); pDC->MoveTo(10,rect.Height()-10); pDC->LineTo(rect.Width()-10,rect.Height()-10); pDC->SelectObject(&pen_white); pDC->MoveTo(m_lineX,m_lineY_after); pDC->LineTo(m_lineX+1,m_lineY); pDC->SelectObject(oldbr); pDC->SelectObject(oldpen); m_lineY_after = m_lineY; UpdateData(FALSE); CDialog::OnPaint(); } } ではよろしくお願いします

  • デスクトップへの描画

    環境 WIN98 VC++6.0 MFC にて ダイアログベースにて デスクトップにキャラクターを書くために、 BOOL CXXX::OnInitDialog(){ キャラクタのリージョンの作成; キャラクタの描画; //ここでは描画されなかった 略 } としましたが、キャラクタは描画されませんでした。 そこで以下のようにしましたが、キャラクタが書かれる前に、リージョンが先に一瞬見えてしまいます。 このような場合はどうすれば良いのでしょうか? void CAdvancedRgnDlg::OnPaint() { キャラクタの描画; }

  • 画像の印刷について

    環境はWIN98 VC++6.0 MFCです。 初めて印刷に挑戦します。 TextOut()で書いた文字は印刷プレビューでちゃんと表示されましたが、以下のようにして取りこんだ画像を印刷プレビューで見ても何も表示されません。 どうしたら印刷できるようになりますか? void CXxxView::OnDraw(CDC* pDC) { CXxxDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: この場所にネイティブ データ用の描画コードを追加します。 CDC myDC; CBitmap myBMP; myBMP.LoadBitmap(IDB_BITMAP3); myDC.CreateCompatibleDC(pDC); CBitmap* oldBMP=myDC.SelectObject(&myBMP); pDC->BitBlt(10,10,60,100,&myDC,0,0,SRCCOPY); myDC.SelectObject(oldBMP); }

専門家に質問してみよう