CPenのCrearPenの色を条件によって切り替えるには


はんにゃ  2011-05-19 18:51:15  No: 72624  IP: 192.*.*.*

WindowsXP VC6.0 MFCで作成中。
void CChildView::OnPaint()
{  // TODO: Add your message handler code here
  CPaintDC dc(this); // device context for painting
の中で  memDC.SelectObject(&fnlLnPen); 
のfnlLnPenの色などを条件で変更するために

//Two-stage-method: first construct the pen
    CPen fnlLnPen;    // second initialize it then Use the pen
    fnlLnPen.CreatePen(PS_SOLID, 4+m_kks/30, m_fnlColor);
として  
其の後   
if( loopNo < 0 )
// to set starting koma of red present koma[knap]
//* CPen fnlLnPen(PS_SOLID, 4+m_kks/30, m_fnlColor);//下に変えた
     fnlLnPen.CreatePen(PS_SOLID, 4+m_kks/30, m_fnlColor2);
else fnlLnPen.CreatePen(PS_SOLID, 4+m_kks/30, m_fnlColor3);

とするとAssertion Errorが表示される。
これを避ける(正常に切り替える)ためにはどうしたらよいでしょうか?

なお、*行のコードは効かないようでしたが  どうしてでしょうか?
一度宣言すると後はむしされるのでしょうか?

編集 削除
仲澤@失業者  2011-05-19 20:48:55  No: 72625  IP: 192.*.*.*

CPen::CreatePen()はGDIオブジェクトハンドルを、事前に破棄しないので、
作成済みのCpenを再作成する場合は、その前に破棄してやらなければ
なりません。

CPen pen;
pen.CreatePen( PS_SOLID ・・・); // 一度作成した場合は
pen.DeleteObject(); // 一旦破棄してからでないと再作成できない
pen.CreatePen( PS_SOLID ・・・); // 再作成

ペンが、HDCにすでに選択済みの場合はその前に選択を外す
必要もあります。

編集 削除
はんにゃ  2011-05-19 21:13:18  No: 72626  IP: 192.*.*.*

すばやい  助言ありがとうございます
見本のように  再設定の前に
fnlLnPen.DeleteObject(); を挿入したところ  無事に通過しました。
ペンが、HDCで  すでに選択済みの場合はその前に選択を外すとのことですが
HDCとは  memDC.SelectObject(&fnlLnPen);のことでしょうか
そうであれば  選択を外すとはどうするのでしょうか
そうでなければ  なにをさすのでしょうか?
重ねて  教えてくだされば  ありがたいです

編集 削除
ホウジョウウサギ  2011-05-20 09:34:45  No: 72627  IP: 192.*.*.*

GDIオブジェクト(Penとか)は DCに選択されていると破棄できないので,
>fnLnPen.DeleteObject()
よりも前に 選択を外す必要があります.

SelectObject()は直前に選択されていたGDIオブジェクトを戻り値で教えてくれるので
>memDC.SelectObject(&fnlLnPen); 
の戻り値を覚えておいて,
それをSelectObject()で選択しなおすことで,
「選択を外す」ことができます.

編集 削除
はんにゃ  2011-05-22 17:01:01  No: 72628  IP: 192.*.*.*

ありがとうございます。
Object Penを作成する⇒pen.CreatePen( PS_SOLID ・・・); // 再作成  
それ以前に
Object Penを破棄する⇒Pen.DeleteObject()する必要がある。
わかりました。こうすると描画線の色が期待どうりになりました。
ところで  Objectを選択するとは
memDC.SelectObject(&Pen);のことだと思いますが、
Pen.DeleteObject()のさらに前に  この選択を外す  即ち  その戻り値で  選択し直すということは
そういうコードになるのでしょうか?
よろしく  おねがいします。

編集 削除
はんにゃ  2011-05-22 17:03:24  No: 72629  IP: 192.*.*.*

誤記でした

そういうコードになるのでしょうか?
⇒どういうコードになるのでしょうか?

編集 削除
ホウジョウウサギ  2011-05-23 14:56:50  No: 72630  IP: 192.*.*.*

そのまま↓のような感じにすればいいのではないでしょうか?

CPen Pen;
Pen.CreatePen( ... );
CPen *pOldPen = DC.SelectObject( &Pen ); //元のpenを覚えておく
/*何かしら描画するコード*/
DC.SelectObject( pOldPen ); //元のpenに戻す
Pen.DeleteObject();

CPenとかSelectObjectとかで検索すれば例は見つかると思います.

http://homepage2.nifty.com/c_lang/mfc/mfc_07.htm
とか.

編集 削除
はんにゃ  2011-05-25 08:47:41  No: 72631  IP: 192.*.*.*

ありがとうございます

以下のように  描画するコードのmemDC.の前にいろいろの条件で
太さや色のことなる描画Penを  animLnPen〜fnlLnPenから選んで  変えています。

そして  fnlLnPenについては  色について  これらのコード以前に  さらに別の条件により  初めの質問で申したように    変えています。

質問1:幾つものPenをCPenで設定することは良いでしょうか?
質問2:それぞれのPenでの描画コード後は  それぞれ  
  DC.SelectObject( pOldPen ); //元のpenに戻す
  Pen.DeleteObject();
とする必要があるでしょうか
これまで  以下のように  処理をしなくても  動作していた。
今回  fnlLnPenについて  CreatePen( ... );で  変更するので
助言のように処理をした。

質問3:元のPenに戻す(選択を外す)というのは  破棄Deleteする前に
どのような意味があるのでしょうか?Objectになにも設定されていない状態は動作が不安定になるとかのことでしょうか

以下  条件でPen種を変えている

      if( trce == 1 )      // 初めのTrace 色決め
      {  
        if( m_swell !=1)  //m_swell  = 0,2,3 and 4 Edgeline
        {  
          if(komaCo ==1) // line color in a Koma alternately changing
          {            
            if( m_swell ==3 || m_swell ==4)  memDC.SelectObject(&animLnPen); // 2011/2/22 ColorButton in one Kolam  
            else                            memDC.SelectObject(&red2Pen);   // day show
            
          } else 
          {  
            if( m_swell ==0)    memDC.SelectObject(&bluGrPen);  // day show
            else if( m_swell ==2)  memDC.SelectObject(&yellowPen); // night show
            else if( m_swell ==3){  memDC.SelectObject(&fnlLnPen);           
            }                        // ColorButton color in next Kolam
            else if( m_swell ==4)  memDC.SelectObject(&animLnPen); // 2011/2/22 edge-line
          }// endof if(komaCo
        } else if( m_swell ==1)      memDC.SelectObject(&blackPen); // swelling paper print
      } else  if( trce == 2 ){       memDC.SelectObject(&fnlLnPen); // for back trace
                        dc.SelectObject( pOldPen ); //元のpenに戻す     
      }                      

 memDC.MoveTo( x4,  y4); 
 memDC.LineTo( x3,  y3); 

あるいは
 memDC.Arc( kx1, ky1, kx2, ky2, x3, y3, x4, y4);

dc.SelectObject( pOldPen ); //元のpenに戻す

編集 削除