プロが教えるわが家の防犯対策術!

よろしくお願いします。
画像を読み込むための、BitBlt関数について、色々調べてみたのですが、どうしても分からない記述が2つあります。ご指導、アドバイスをお願いします。

1、サンプルのソースを参考にしているのですが、BitBlt関数の第2、第3の記述の意味として、
『PAINTSTRUCT構造体のポインタpsが、左隅上、を参照している』と解釈したのですが、第4、第5引数の、-(引く)の意味が理解できません。

2、画像を2種類表示するためメニューに、『オプション1とオプション2』を作り、オプション1はコピー元と同じ画像を表示、

オプション2は、ラスタオペレーションを選択可能にして、選択した画像を表示すると言うものですが、DWORD dwRop; を宣言し『第9引数をNOTSRCCOPY』として、二つ目の画像を表示する case文に dwRop = NOTSRCCOPY; を追加したのですがうまく行きません。多分 『dwRop』の使い方に問題があるのかと思うのですが、うまく表示されません。
因みに、 BitBlt関数の第9引数が『SRCCOPY』の時は、正常に2種類の画像が表示されます。

/*ウィンドウプロシージャ*/
 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 
{
HDC hdc; 

DWORD dwRop; //追加した 

PAINTSTRUCT ps; 
HBITMAP hBmp; 
HDC hdc_memx; 

switch(msg){ 
case WM_CREATE: 
hdc = GetDC(hWnd); 

hBmp = LoadBitmap(hInst, "MYBMP1"); 
if(hBmp == NULL){ 
MessageBox(hWnd, "画像1のロードに失敗しました", "エラー", 
MB_OK | MB_ICONWARNING); 
return 0; 
} 
hdc_mem1 = CreateCompatibleDC(hdc); 
SelectObject(hdc_mem1, hBmp); 
DeleteObject(hBmp); 

hBmp = LoadBitmap(hInst, "MYBMP2"); 
if(hBmp == NULL){  
MessageBox(hWnd, "画像2のロードに失敗しました", "エラー",  
MB_OK | MB_ICONWARNING); 
return 0; 
}
hdc_mem2 = CreateCompatibleDC(hdc); 
SelectObject(hdc_mem2, hBmp); 
DeleteObject(hBmp); 

ReleaseDC(hWnd, hdc); 
break; 

case WM_PAINT: 
BeginPaint(hWnd, &ps); 

if(show_no == 1)
hdc_memx = hdc_mem1; 

if(show_no == 2)
hdc_memx = hdc_mem2; 

BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
hdc_memx, ps.rcPaint.left, ps.rcPaint.top,
SRCCOPY); 


// PATCOPYにして,IDM_ANIME2に、dwRop=NOTSRCCOPY
//を追加しても変更されないし、画像の表示が出来ない
EndPaint(hWnd, &ps); 
break;

case WM_COMMAND:
switch (LOWORD(wp)){
case IDM_ANIME1:
show_no = 1;
     //dwRop = SRCCOPY //追加したが変化なし
InvalidateRect(hWnd, NULL, TRUE);
break; 

case IDM_ANIME2:
show_no = 2;

//dwRop = NOTSRCCOPY; //追加したが変化なし

InvalidateRect(hWnd, NULL, TRUE);
break; 

case IDM_END:
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
break; 

case WM_DESTROY:

DeleteDC(hdc_mem1);
DeleteDC(hdc_mem2);
PostQuitMessage(0);
break; 

default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}

このQ&Aに関連する最新のQ&A

A 回答 (3件)

ps.rcPaint.right - ps.rcPaint.left,


ps.rcPaint.bottom - ps.rcPaint.top,
は 書き換えが必要な部分つまり 無効になっている部分を算出しています

BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
hdc_memx, ps.rcPaint.left, ps.rcPaint.top,
SRCCOPY);
の SRCCOPYを dwRopに変更します
つまり
BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
hdc_memx, ps.rcPaint.left, ps.rcPaint.top,
dwRop);

dwRopを設定する部分を実装します ... メニューイベントの対応とかです
dwRopが大域変数ならいいのですが WndProcのローカル変数ならstatic属性を指示しましょう

PATCOPYはデバイスコンテキストに指定されたブラシをコピーするのに用います
BitBltで指定する場合 第一引数のデバイスコンテキストで選択されているブラシが対象です
普通は PatBltで使います

この回答への補足

アドバイス、有難うございます。
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
については、VTClientさんのアドバイスで、少し意味が分かりかけていたのですが、『画像を算出しているのではなく、無効領域を算出していたのですね』 すっきりしました。
また、
BitBlt()の、第9引数の、『SRCCOPY』を 『変数のdwRop』に変えるのは 『もしかしたら』 と思ったのですが、これで確信が持てました。
変更すると、ソースの記述や、メニューリソースも変更ですね。

それと、PATCOPYの使い方が間違ってました。ご指摘有難うございます。
ラスタオペレーションの使い方も、もう少し調べてみます。
これから早速ソースを変更して試してみます。
結果は、お礼のほうに報告したいと思います。

補足日時:2007/10/16 21:53
    • good
    • 0
この回答へのお礼

アドバイス有難うございます。
早速 『BitBlt()の、第9引数』をdwRopに 変更し、メニューリソースも変更しました。

ファイルとオプションを作り、ファイルからは画像1、画像2の選択肢
オプションには、ラスタオペレーションの選択肢を作りました。

結果、ぶじにコンパイルできました。
ただ、一つ気になることがあるのですが、ファイルをクリックした時に、クライアント領域が真っ黒く表示されます。
その後に画像を選択すると、クライアント領域が白く変わり、そこに画像が表示されます。
この真っ黒になる原因が理解できません。これから白いクライアント領域に修正したいと思っっています。
何かお気づきでしたら、アドバイスをお願いします。

お礼日時:2007/10/17 22:49

show_noの値が初期化されていない場合または 1or2以外の場合


hdc_memxが不定になってしまっていませんか

show_noが 1or2以外だったら BitBltを実行しないようにするとか
WM_CREATEで LoadBitmap(hInst,"MYBMP1")が成功したら show_noを1に初期化するとか

デバイスコンテキストに選択したグラフィックオブジェクトを選択をはずす前に DeleteObjectで削除するのはお勧めしません
MSDNなどで DeleteObjectなどを検索してみてください
    • good
    • 0
この回答へのお礼

再度のアドバイス、有難うございます。
ご指摘のとおり 『show_no1,show_no2 』以外のときの処理が出来ていませんでした。

WM_CREATEで、ウィンドウが作られたら画像を表示する様にしたら、改善されました。
後は、いろいろの記述を試して見ます。

貴重なアドバイスを有難うございました。

お礼日時:2007/10/19 22:37

<1>


BitBlt(ps.hdc, ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
hdc_memx, ps.rcPaint.left, ps.rcPaint.top,
SRCCOPY);



ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,

は幅、高さを指定します。つまり座標が (10,10) - (100,80)
であるとき、幅は、100 - 10 = 90 / 高さは 80 - 10 = 70
ですから差分で算出するわけです。
でもクライアント座標は (0,0) - になるので引く必要はないの
ですがスクリーン座標を想定して引くべきですね。

<2>
DWORD dwRop; //追加した

static DWORD dwRop;

に変更してはだめですか?

この回答への補足

早いアドバイス有難うございます。
ps.rcPaint.right - ps.rcPaint.left,
ps.rcPaint.bottom - ps.rcPaint.top,
の記述を分かりやすく説明していただき、有難うございます。
rcPaintメンバ(無効領域)から、無効でない部分(画像)を算出しているのですね。

また、『DWORD dwRop』を、『static DWORD dwRop』 に変更して試してみたのですが、
画像2は、反転表示されませんでした(普通の画像)。

この時、BitBlt()の、第9引数は、『SRCCOPY』ですが、ここを『PATCOPY』に変更すると、画像1、画像2、どちらも表示されません。
第9引数の設定が悪いのでしょうか?

色々調べてみますが、何かお気づきの所がありましたら、アドバイスをお願いします。

補足日時:2007/10/15 11:45
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

QBitBlt関数について

お世話になっております。
 
またまた質問ですが、
 
画像を表示したいので、BitBlt関数を使ってみたんですが、
 
エラーもなく、実行できました。
 
しかし、画像が表示されません。
 
サイトや本を何回も見て、間違いがないか見たんですけど、間違いがまったく見当たりません。
 
LRESULT CALLBACK VisualProc (
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {

switch(uMsg) {
case WM_CREATE:
memdc = CreateCompatibleDC( NULL );
hBitmap = ( HBITMAP )LoadImage( NULL , TEXT("player.bmp") , IMAGE_BITMAP ,
0 , 0 , LR_LOADFROMFILE | LR_CREATEDIBSECTION );
SelectObject(memdc, hBitmap);
return 0;
case WM_PAINT:
hdc = BeginPaint(VisualWnd,&ps);
BitBlt(hdc, 30,30, 34, 32, memdc, 0, 0, SRCCOPY);
EndPaint(VisualWnd,&ps);
return 0;

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

画像は、リソースで追加→既存の項目→ピクチャ
でやりました。
それで、ピクチャからプロジェクトのファイルに移動させました。
 
それでもできません。
 
 
一体どのようにやればいいのでしょうか。
わかりやすく教えてください。

お世話になっております。
 
またまた質問ですが、
 
画像を表示したいので、BitBlt関数を使ってみたんですが、
 
エラーもなく、実行できました。
 
しかし、画像が表示されません。
 
サイトや本を何回も見て、間違いがないか見たんですけど、間違いがまったく見当たりません。
 
LRESULT CALLBACK VisualProc (
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {

switch(uMsg) {
case WM_CREATE:
memdc = CreateCompatibleDC( NULL );
hBitmap = ( HBITMAP )LoadImage( NULL , TEXT("player.bmp"...続きを読む

Aベストアンサー

#3です。

#3の補足について。

> 1.はい、staticです。

それで大丈夫のはずです。

> 2.リソースは削除してやってみました。できません。

では、表示させたいビットマップファイルは実行ファイル(*.exe)とは別に存在
する(ファイル名"player.bmp"のファイルとして存在している)と言うことですね?

それならば"player.bmp"は、実行ファイル(*.exe)と同じフォルダ(ディレトリ)
に置いて下さい。

もしも、Debug版とRelease版で別々のフォルダに実行ファイルを作成している
場合は、"player.bmp"も両方のフォルダにそれぞれコピーしておいて下さい。
注)開発ツールの画面上のプロジェクトツリー等のフォルダではなく、実際の
  ディスク上のフォルダにビットマップファイルを置いて下さい。

なお、LoadImage関数の引数での"player.bmp"の記述をフルパス(ドライブ名
から始まるフルパス名)で指定した場合は、"player.bmp"を複数コピーする
必要はありません。

> 3.第一引数は、再描画するウィンドウのハンドルと本に書いてあったので、
> VisualWndにしました。

VisualWnd が示すウィンドウとは、アプリケーションのメインウィンドウ(クライ
アント領域)とは違うものなのでしょうか?

その本にどう書かれているか判りませんが、質問者さんが今回書かれた
プログラム(ソースコード)の内容により、関数の引数などの記述もその状況に
合わせて変更しなくてはいけません。

ですので、ご自分で記述した変数などの意味、及び、使用している関数等の
使い方、記述方法などをヘルプ、書籍、WEB等で調査しその内容をよく理解
した上でコードを記述なさって下さい。

取りあえず今回について言えば、VisualWnd の記述を VisualProc関数の引数
の記述にあわせて hWnd に変更して検証してみては如何でしょうか?

あと、デバッグ環境が使えるのならプログラムをステップ実行で実行しながら
各変数の値が正常か、及び、各関数の戻り値などが正常値で返されているか
どうかを一つ一つ検証しながらプログラムを追ってみることをお勧め致します。

以上です。

#3です。

#3の補足について。

> 1.はい、staticです。

それで大丈夫のはずです。

> 2.リソースは削除してやってみました。できません。

では、表示させたいビットマップファイルは実行ファイル(*.exe)とは別に存在
する(ファイル名"player.bmp"のファイルとして存在している)と言うことですね?

それならば"player.bmp"は、実行ファイル(*.exe)と同じフォルダ(ディレトリ)
に置いて下さい。

もしも、Debug版とRelease版で別々のフォルダに実行ファイルを作成している
場合は、"player.bmp"も両...続きを読む

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング