• ベストアンサー

MFC C++

MFCでソリューションを新規作成した時に作られるプログラムにちょこちょこと手を加えています。 以下のプログラムは、画面の中心に黒い円を描くプログラムの一部です。 void CChildView::OnPaint() { CPaintDC dc(this); // 描画のデバイス コンテキスト CRect rect; GetClientRect(&rect); CPoint center = rect.CenterPoint(); const int sizeCircle = 60; CSize offset(sizeCircle / 2, sizeCircle / 2); CSize size(sizeCircle, sizeCircle); CRect rectCircle(center - offset, size); CBrush brush(RGB(0, 0, 0)); CBrush* pBrushOrg = dc.SelectObject(&brush); dc.Ellipse(rectCircle); dc.SelectObject(pBrushOrg); } どなたか以下のことを教もらえないでしょうか。 (1)CSize size(sizeCircle, sizeCircle);の部分ですが、size()はCSizeのメンバ変数ではないと思うのですが、size()の型がCSizeになっているのはどうしてでしょうか? (2)上の続きで、size()関数は見る限りどこにも定義されていなかったのですが、どこかに元々定義があるのでしょうか?(元々というのは、Microsoft側で定義してくれているということです。) (3)dc.Ellipse(rectCircle);の部分で、dc.とはどういう意味でしょうか? どなたかお願いします。

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

  • ベストアンサー
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.2

sizeは変数名であって、関数名ではありません。 C++では変数を定義する際、変数名の後ろに引数を書くことができるのです。 CSize size(sizeCircle, sizeCircle); と書くのは、 CSize size; size.cx=sizeCircle; size.cy=sizeCircle; と書くのと同じ動作をします。 なぜ同じ動作になるかというと、 CSize( int initCX, int initCY ); という「コンストラクタ」が定義されているからです。 これ以上の詳しい話は、「コンストラクタ」を調べるといろいろ書いてあるはずです。

その他の回答 (1)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

広い意味では関数ですが 本来はコンストラクタといいます コンストラクタにはそのオブジェクトを宣言する際に引数を伴うものと不要なもの(または省略可能なもの)があります お示しのコードの中の CRect rect; CRect rectCircle(center - offset, size); のrectやrectCircleはともに CRect型ですが rectは引数がありません rectCircleは引数ありで 関数のような表記になっています CRect型でいえば CRect( int l, int t, int r, int b ); //4個の点 CRect( const RECT& srcRect );    // 元になる CRectから CRect( LPCRECT lpSrcRect );     // RECT構造体を元にする CRect( POINT topLeft, POINT bottomRight ); // 左上と右下のPOINT構造体 といった具合に ほかの方法で構築することも可能です 同様に CSizeについても CSize( ); CSize( int initCX, int initCY ); CSize( SIZE initSize ); CSize( POINT initPt ); CSize( DWORD dwSize ); といった種類のコンストラクタがあります 2番目のCSize( int initCX, int initCY )を使って構築しているのですよ CSize::CSize(int initCX, int initCY ) として定義されていて CSize objSize( 50, 50 ); と定義すると objSizeが生成される際に CSize::CSizeが呼ばれて 必要な初期化が行われます

関連するQ&A

  • 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

  • MFCでボタンを押して図形を操作するには

    Visual studio 2008のMFCで、とあるプログラムを作っております。 ボタンをクリックすると円が出てきて、さらにクリックするとその下に円が表示されるというプログラムまで作りました。 void C***Dlg::OnBnClickedButton1(){ CDC* pDC=m_pict.GetDC(); CRect rect; m_pict.GetClientRect(&rect); pDC->Rectangle(&rect); CPen pen_red(PS_SOLID,1,RGB(255,0,0)); CBrush br_yellow(RGB(255,255,0)); CPen* oldpen=pDC->SelectObject(&pen_red); CBrush* oldbr=pDC->SelectObject(&br_yellow); pDC->Ellipse(-252,i-43,-212,i-3); i=i+48; UpdateWindow(); pDC->SelectObject(oldpen); pDC->SelectObject(oldbr); // TODO: ここにコントロール通知ハンドラ コードを追加します。 } とりあえずOnBnClickedButton1関数はこんな感じです。 ここから、 (1)クリックすると円が自動で動き、途中で止まり、しばし経ってから動き出してやがて上へ消えてゆく。 (2)2つ目の円も同じように動くが、1つ目の円が止まっていて重なりそうになったらその手前で止まる。 (3)1つ目の円が上に消えたら、2つ目の円が動き出し、以降は(1)と同じ動きをする。 このようなプログラムを作りたいのですが、初心者のためどのようなツールをどのように使えば良いのかわかりません。 どなたがヒントだけでもご教授頂けませんでしょうか?

  • ダイアログ上でマウスが止まった事を認識できますか。

    ダイアログ上でマウスが止まった事を認識できますか。 MFCを駆使してダイアログに画像を出力するまでは できました。しかし,そのあと,画像上にマウスで四角の 領域を囲みたいのですが,うまくいきません。 以下にマウスが動く時のソースを記します。 void CDlgDefine::OnMouseMove(UINT nFlags, CPoint point) {  e_pt=point;  CBrush Brush;  CBrush* pBrush;  //s_ptはマウス左ボタン押下時,CPointから座標を取得しています  CRect rect(s_pt.x,s_pt.y,e_pt.x,e_pt.y);  rect.NormalizeRect();  Brush.CreateSolidBrush(RGB(0, 255, 0));  pBrush= pDC->SelectObject(&Brush);  pDC->FrameRect(rect,pBrush);  Invalidate();//これが無い場合,マウスが動くと沢山四角が描かれてしまうのです。 } これで動かすと,マウスが動く瞬間四角がでるのですが,止まると消えてしまいます。 マウスが止まった時,四角がダイアログの画像上に描かれる方法はないでしょうか?

  • 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(); } } ではよろしくお願いします

  • クライアント領域を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(); }

  • VC++でのアイコン背景透過について

    VC++2013 MFC環境です。 プログラムで○や×などの記号のアイコンを描画し、PNG,GIF,JPEGの形式でファイルに保存したいです。その時、アイコンの背景を透過したいのですがうまくいきません。 CDCクラスとCImageクラスを使用しアイコンの出力をしています。 背景透過について調べていくつか使えそうな関数があり試したのが、TransparentBltという関数で、デバイスコンテキストを二つ用意して、片方に記号を描画し、透過したい色を指定してもう片方にコピーすると指定した色が透過になる?と解釈しプログラム組みましたが結果は真っ黒の画像でした。 ここで完全に手が止まってしまい、質問させていただきます。 以下ソース CImage Image, image2; Image.Create( 50, 50, 24 ); image2.Create( 50, 50, 24 ); CDC* pDC = CDC::FromHandle( Image.GetDC( ) ); CDC* pdc2 = CDC::FromHandle( image2.GetDC( ) ); CRect rect( 0, 0, 50, 50 ); CPen BlackPen( PS_SOLID, 3, RGB( 0, 0, 0 ) ); CBrush WhitBrush( RGB( 255, 255, 255 ) ); CBrush BlackBrush( RGB( 0, 0, 0 ) ); pDC->FillRect( &rect, &WhitBrush ); pDC->SelectObject( &BlackPen ); pDC->SelectObject( &WhitBrush ); pDC->Ellipse( 5, 5, 45, 45 ); COLORREF col = Image.GetPixel( 0, 0 ); pdc2->TransparentBlt( 0, 0, 50, 50, pDC, 0, 0, 50, 50, col ); Image.SetTransparentColor( col ); image2.Save( L"c:\\icon\\maru.png" ); Image.ReleaseDC( ); image2.ReleaseDC( ); 他にも実装例があれば教えてください。 C++や画像生成に関しては経験がありません。

  • 変数の代入について

    ダイアログベースで、ダイアログ1からダイアログ2を開きダイアログ1のエディットボックスのデータをダイアログ2に表示する下記コードを教わりました。 変更後のようにしても問題ないと思いましたが、'dlg' は定義されていない識別子です。とエラーが出ます。 どうしてなのかお教えていただきたいのですが、 よろしくお願いします。 <変更前> CSubDlg dlg2; dlg2.m_strText = strText; dlg2.DoModal(); <変更後> void CSubDlg::OnPaint() { m_strText = dlg.strText; ちなみにdlgはウィザードが作ったコードで、 CMainDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); ダイアログ1のことだと思うのですが。。。。 ************************** メインダイアログとしてCMainDlgを例にしますが、かなり割愛します。 このダイアログには、Editが貼り付けられているとします。Editコントロールに割り当てたIDをIDC_EDIT_INPUTだと仮定します。 DDXとかのデータ変換を使う方法もありますが、ここでは単にデータを取得します。 // // OKボタンが押された時の処理 // void CMainDlg::OnOK() { // データの取得 CString strText; GetDlgItemText(IDC_EDIT_INPUT, strText); CSubDlg dlg2; dlg2.m_strText = strText; dlg2.DoModal(); } class CSubDlg : pbulic CDialog { public: CString m_strText; // 親から渡される文字列を格納する変数 ・ ・ ・ ・ ・ }; あとは、CSubDlgのOnPaintでテキストを描画します。 void CSubDlg::OnPaint() { // テキストをクライアント領域の中央に描画 CRect rect; GetClientRect(rect); CPaintDC dc(this); dc.TextOut(m_strText, rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); }

  • MFCでネガポジ変換

    以下のプログラムはネガポジ変換をするプログラムです。MFCで最初に作られるプロジェクトのCChildView.cppのOnPaint関数に実装しました。デバッグするとウィンドウ全体が真っ黒になるはずです。が、なぜか添付のファイルのように白黒の縞模様になってしまします。ちなみに私はVC++2008を使っています。知人にも相談して、VC++2005で全く同じプログラムで試してもらいましたが、そちらではウィンドウが真っ黒になって成功しました。違いはおそらく2008か2005かということだけ何のです。 何か原因をご存知の方がいらしたら教えてもらえないでしょうか。 void CChildView::OnPaint() { CPaintDC dc(this); // 描画のデバイス コンテキスト int w = dc.GetDeviceCaps(HORZRES); //DCの幅を得る int h = dc.GetDeviceCaps(VERTRES); //DCの高さを得る int i, j; for(j=0; j<h; j++) { for(i=0; i<w; i++) { //DCの(i,j)位置から色を得る COLORREF c = dc.GetPixel(i, j); //色を取得 if(c!=CLR_INVALID) { //反転したr,g,b値を取得 int r = 255- GetRValue(c); int g = 255- GetGValue(c); int b = 255- GetBValue(c); c = RGB(r, g, b); //その画素を置く dc.SetPixel(i, j, 0); } } } }

  • ゲームのように、きれいにフェードアウトしたい

    ゲームのように、きれいにフェードアウトしたいのですが、どうすればいいですか? よろしくお願いします。 #include<atlimage.h> class Picture { // ここに、いろいろな変数、関数があります // 描画すると、ちらつきます void Draw(CDC *pDC) { // (CImage)image,(CDC)*imageDC,SpDCは、クラスの宣言、この関数の外 // (CBitmap)cbmp,*oldcbmp 同上 // (CBrush)Brush 同上 imageDC=CDC::FromHandle(image.GetDC()); BLENDFUNCTION bf; bf.BlendOp=AC_SRC_OVER; bf.AlphaFormat=0 ; bf.BlendFlags=0; bf.SourceConstantAlpha=(BYTE)GetImageAlpha(); // 255~徐々に減少 SpDC.FillRect(CRect(0,0,GetImageSize().cx,GetImageSize().cy),&Brush);// CSize GetImageSize(){return imageSize;} イメージの高横 SpDC.AlphaBlend(0,0,GetImageSize().cx,GetImageSize().cy,imageDC,0,0,GetImageSize().cx,GetImageSize().cy,bf); pDC->BitBlt(0,0,GetImageSize().cx,GetImageSize().cy,&SpDC,0,0,SRCCOPY); image.ReleaseDC(); // デストラクタにて、SpDC.SelectObject(oldcbmp);cbmp.DeleteObject();SpDC.DeleteDC();Brush.DeleteObject(); } }; //補足ですが、SetTimer()でInvalidate()しています。

  • リッチエディットの独自描画で文字の位置をそろえたい

    リッチエディットのWM_PAINT命令をフックすることで、改行文字を視覚化するプログラムを組んでいるのですが、GetCharPos命令で取得した文字位置の座標は左上隅のものなので、一般のテキスト文字と描画した文字がうまく横並びになりません。また、GetTextExtentでフォントの高さを取得することで、水平位置を調整しようと思ったのですが、フォントの高さとリッチエディットの一行単位の高さが異なるためか、以下のコード例(MFCにて作成)でもやはりきれいに揃いません(文字数制限のため、一部コードを省いています)。 void CRichEditEx::OnDrawFormatChar() { CString strText; GetWindowText(strText); CPoint ptCharL; CClientDC dc(this); //m_foFormatCharは //SetDefaultCharFormat()で登録したフォントと //サイズ・フォント名ともに同一 CFont* pfoOld = dc.SelectObject(&m_foFormatChar); CSize sizChar = dc.GetTextExtent(_T("W")); CRect rectClient; GetRect(&rectClient); int i, iPos = 0; while(iPos != -1){ iPos = strText.Find(_T('\n'), iPos); if(iPos != -1){ ptCharL = GetCharPos(iPos); if(ptCharL.y > rectClient.bottom) break; if(rectClient.PtInRect(ptCharL)){ dc.DrawText(_T("N"), CRect(ptCharL, ptCharL + sizChar), DT_SINGLELINE | DT_VCENTER); } } } フォントの上下余白を含めた高さ、あるいは、リッチテキストの1行単位の高さが取得できれば何とかなると思うのですが、よい方法はございますでしょうか。

専門家に質問してみよう