図形描画について教えてください – 固定ページ 2 – プログラミング – Home

図形描画について教えてください
 
通知
すべてクリア

図形描画について教えてください

固定ページ 2 / 2

Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> つたないソースですが、わかりやすくするには直したほうが良いところがありましら、
> アドバイスしてください。お願いします

見易さについて、ちょっとだけ。

CClientDC myCLDC(mybyouga);
使ってません?(抜粋時の問題で、本当は使ってるのかも知れませんけど。

きわめて個人的な意見ですが、
CDC *pmyDC = &myDC;
BitBltの引き数にしか使わないなら、特に不要かと。
同じものを複数の名前で参照すると、(検索なども含め)トレースしにくくなると思ってます。
別名をつけるならつけるで、つけた後はそちらしかつかわないとか、
使う直前で作成する(宣言意図と使用位置が離れていればいるほど、「浮き」やすくなる。

あと、API のエラーチェックがないのは、テスト用/掲示用に抜粋などのためですか。
きちんとやっておいたほうがいいです。


返信引用
まりお
 まりお
(@まりお)
ゲスト
結合: 19年前
投稿: 16
Topic starter  

if(radio1->GetCheck()){
pDC->Ellipse(x+rad,y+rad,x-rad,y-rad);
}else if(radio2->GetCheck()){
pDC->Rectangle(x+rad,y+rad,x-rad,y-rad);}

pDC->BitBlt( 0, 0,myRECT.Width(),myRECT.Height(), pDC, 0, 0, SRCCOPY )

EllipseはpDCに対してやりたいです。これで表示はできたのですが図形が消えてしまい
ます。何がいけないのでしょうか?何か足りないんでしょか?


返信引用
REE
 REE
(@REE)
ゲスト
結合: 23年前
投稿: 240
 

図形の上にビットマップを描くのと、
ビットマップの上に図形を描くのの違いでしょう。
順番換えればいいのでは?


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

> これで表示はできたのですが図形が消えてしまいます。

情報不足。どのように消えるのですか?
- ちらっと描かれたかとおもうと消えてしまう?
- その絵の上に他のWindowで覆いをかけ、覆いを取ると消えている?

> 何がいけないのでしょうか?

おそらくは「適切なタイミングで描画していない」
「適切なタイミング」とは「書き直してくれ」とWindowsからお願いされたとき。
# それが OnPaint/OnDraw です。


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> EllipseはpDCに対してやりたいです。これで表示はできたのですが図形が消えてしまい
> ます。何がいけないのでしょうか?何か足りないんでしょか?

???
最終的には pDC に対してやりたいんでしょうが、BitBlt で上書きしてるのですから、
その前に何を一生懸命かいても無駄なのでは?

if(radio1->GetCheck()){
pDC->Ellipse(x+rad,y+rad,x-rad,y-rad);
}else if(radio2->GetCheck()){
pDC->Rectangle(x+rad,y+rad,x-rad,y-rad);}

こっちの pDC を pmyDC にすれば、その後の BitBlt で pDC に転送されませんか。
もしくは、BitBlt の後に、pDC に描画とか。

> pDC->BitBlt( 0, 0,myRECT.Width(),myRECT.Height(), pDC, 0, 0, SRCCOPY )

自分から自分に転送ですか?

いずれにせよ、「とりあえず試行錯誤」ではなく、一度処理を整理して、
新規に書き起こすくらいのつもりで、変数名なども整理したほうがいいと思います。

ただの myDC とか、何の用途に使っているか分かりにくいので、
ご自身でも混乱していませんか。


返信引用
まりお
 まりお
(@まりお)
ゲスト
結合: 19年前
投稿: 16
Topic starter  

どういうことですか?自分が添付したソースのどこを変えたらいいんですか。
REEさんが言ってるのはまずビットマップを先にピクチャーボックスに出してから、
図形を描けといっているんですよね?


返信引用
まりお
 まりお
(@まりお)
ゲスト
結合: 19年前
投稿: 16
Topic starter  

どういうことですか?自分が添付したソースのどこを変えたらいいんですか。
REEさんが言ってるのはまずビットマップを先にピクチャーボックスに出してから、
図形を描けといっているんですよね?


返信引用
まりお
 まりお
(@まりお)
ゲスト
結合: 19年前
投稿: 16
Topic starter  

二回送りましたが気にしないでください。間違えて送りました


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

> どういうことですか?自分が添付したソースのどこを変えたらいいんですか。

「どう直したいか」でどこを直すかが決まります。どこを直すかは望む直し方しだいです。
どう直したいのかは まりお さんにしか分からないと思います。

ます、思い描く操作を時系列でまとめてみてください。

次に、現状のこれらについて、どのタイミングでどんな操作をしているか、
時系列でまとめてみてください。
pDC
myCLDC
myDC
pmyDC
 各画面を模した紙を用意して、書いて、重ねて…とか順番にやってみたり。

現在の操作は、まりお さんの本来思い描いている操作になっていますか。どう違いますか。

思い描く操作に直してください。直し方に困ったら、この時点で上で検討した内容と一緒に
相談してみて下さい。

そして、それぞれの用途を明確にし、もっと分かりやすい用途のわかる名前を付けてみてください。


返信引用
まりお
 まりお
(@まりお)
ゲスト
結合: 19年前
投稿: 16
Topic starter  

皆さんのおかげで何とかできました。しかし、今度は二回目以降が描画できなくなりま
した。何故ですか。教えていただけませんか。
CWnd* mybyouga=GetDlgItem(IDC_byouga);
//デバイスコンテキストの取得
pDC=mybyouga->GetDC();
CRect myRECT;
myRECT.SetRect(0,0,512,512);

myDC.CreateCompatibleDC(pDC);
myBmp.CreateCompatibleBitmap(pDC,myRECT.Width(),myRECT.Height());
myDC.SelectObject(myBmp);
myDC.FillSolidRect(myRECT,RGB(255,255,255));

/*ピクチャーボックスのサイズ取得*/
mybyouga->GetClientRect(myRECT);

CSpinButtonCtrl* spin1=(CSpinButtonCtrl*)GetDlgItem(IDC_SRADIUS);
CSpinButtonCtrl* spin2=(CSpinButtonCtrl*)GetDlgItem(IDC_SPIN_Z_X);
CSpinButtonCtrl* spin3=(CSpinButtonCtrl*)GetDlgItem(IDC_SPIN_Z_Y);

rad = GetDlgItemInt(IDC_RADIUS);
spin1->SetPos(rad);
int zx,zy;
zx = GetDlgItemInt(IDC_X);
spin2->SetPos(zx);
x = zx + 256;
zy = GetDlgItemInt(IDC_Y);
spin3->SetPos(zy);
y = 256- zy;

if(rad < 1 || rad > 256 || zx < -256 || zx > 256 || zy < -256 || zy > 256)
{
AfxMessageBox(L設定範囲超えてるよ!直せ);}

CBrush myBrush;
myBrush.CreateSolidBrush(RGB(red,green,blue));
myDC.SelectObject(&myBrush);
CButton* radio1=(CButton*)GetDlgItem(IDC_RADIO1);
CButton* radio2=(CButton*)GetDlgItem(IDC_RADIO2);
if(radio1->GetCheck()){
myDC.Ellipse(x+rad,y+rad,x-rad,y-rad);
}else if(radio2->GetCheck()){
myDC.Rectangle(x+rad,y+rad,x-rad,y-rad);}

pDC->BitBlt(0,0,512,512,&myDC,0,0,SRCCOPY );


返信引用
Ban
 Ban
(@ban)
Prominent Member
結合: 5年前
投稿: 776
 

「本物」を張ってもらっているわけでもなさそうですし、
提示されてない部分次第ですが、ぱっと見、
生成あたりでエラーが発生してそうなソースに見えます。

エラーを返す関数を読んだら、結果を確認するのは基本です。
最低でもASSERT なりトレースなりいれてください。

> つたないソースですが、わかりやすくするには直したほうが良いところがありましら、

適当に直してみたのですが、これで元の意図と合っているは不明です。
エラーチェックとかもASSERT程度しか書いてないですし、
コンパイルもしてませんので、あくまで参考程度ですが。

好みの問題も大きいものですが、一般的には、
変数を使いまわすのは避けた方がいいです。定数を直接使うのも避けた方がいいです。
同じような処理は、関数などにして名前付けしたほうがいいです。
処理の中にコントロールの取得などが入ると流れがみにくくなりがちなので隠蔽した
方がいいです。メンバで持ってしまうのも一考の余地アリです。

// 他のメンバ関数たち

inline int
UpdateSpinPos(UINT resid, UINT spinid)
{
BOOL result = FALSE;
int value = GetDlgItemInt(resid, &result);
ASSERT(resul);
CSpinButtonCtrl* spin = dynamic_cast<CSpinButtonCtrl*>GetDlgItem(spinid
);
if(spin != NULL) spin->SetPos(value);
// else でTRACEなり。
return value;
}
inline bool
IsChecked(UINT radid)
{
CButton* radio = dynamic_cast<CButton*>GetDlgItem(radid);
if(radio == NULL)
{
// TRACEなり。
return false;
}
return radio->GetCheck() != FALSE;
}

struct Range
{
int min_;
int max_;

Range():min_(0), max_(0){}
Range(int min, int max):min_(min), max_(max){}

bool
IsIn(int value)const
{
return min_ <= value && value <= max_;
}
}

// これらはクラスに関連づいた定数
static const Range RadiusSpinLimit(1, 256);
static const Range XSpinLimit(-256, 256);
static const Range YSpinLimit(-256, 256);

static const CRect BackRect(0,0,512,512);
// 画面サイズとは異なるサイズで作ってBitBltしても意図どおり?
// 画面サイズと一致/画面サイズ固定ならこの変数の意味は?単に初期値?

// これらは普通、ウィンドウの初期化に書く。
BackDC.CreateCompatibleDC(pDC);
BackBmp.CreateCompatibleBitmap(pDC,BackRect.Width(),BackRect.Height());
BackDC.SelectObject(BackBmp);
BackDC.FillSolidRect(BackRect,RGB(255,255,255));
// 破棄/解放処理がかかれてないので不明ですが…毎回再生成してるのでしょうか。
// いずれにせよエラーチェックはするべきです。
// 現状、二度目が書かれないのはどこかで失敗してたりしないですか。

// 描画
{
CWnd* mybyouga=GetDlgItem(IDC_byouga); ASSERT_VALID(mybyouga);
CDC* pDC = mybyouga->GetDC(); ASSERT_VALID(pDC);

/*ピクチャーボックスのサイズ取得*/
CRect PictRect; mybyouga->GetClientRect(PictRect);

int radius = UpdateSpinPos(IDC_RADIUS, IDC_SRADIUS);
int inputX = UpdateSpinPos(IDC_X,IDC_SPIN_Z_X);
int inputY = UpdateSpinPos(IDC_Y,IDC_SPIN_Z_Y);
if( ! (RadiusSpinLimit.IsIn(rad) && XSpinLimit.IsIn(inputX) && YSpinLimit.
IsIn(inputY)))
{
AfxMessageBox(L設定範囲超えてるよ!直せ);
}

int x = inputX + 256; // 補正の基準256はどこだろう。
int y = 256 - inputY;

CBrush myBrush;
BOOL result = myBrush.CreateSolidBrush(RGB(red,green,blue));
ASSERT(result);
BackDC.SelectObject(&myBrush);

if(IsChecked(IDC_RADIO1))
{
result = BackDC.Ellipse(x+rad,y+rad,x-rad,y-rad);
}
else if(IsChecked(IDC_RADIO2))
{
result = BackDC.Rectangle(x+rad,y+rad,x-rad,y-rad);
}
ASSERT(result);

result = pDC->BitBlt(PictRect.left,PictRect.top,PictRect.right,
PictRect.bottom,&BackDC,0,0,SRCCOPY);
ASSERT(result);

........
....


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

提示されているコードが部分的なので他の部分が適切なのかの判断がつきません。
今の提示されている情報だけでは、
「二回目以降が描画できなくなりました。何故ですか。教えていただけませんか。」
この問いに正確に答えるのは無理です。

考えられるのは、描画対象領域が無効化されていないのではないかという事ぐらいです。
Windowsの描画の仕組みがわからないままに関数の呼び出しをひたすらしていませんか?
Windowsでうまく描画の仕組みを回すにはそれなりの手順と言うのがあります。
この手順を理解していないといつまでたっても同じ事の繰り返しになると思うのですが。


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

返信する

投稿者名

投稿者メールアドレス

タイトル *

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