winapi32での画像ぶれについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
alulu

winapi32での画像ぶれについて

#1

投稿記事 by alulu » 7年前

はじめまして、よろしくお願いします。
winapiでjpeg画像をドラッグ&ドロップできるプログラムを作っています。
ですが、ドラッグ&ドロップ時に画像がすごくぶれてしまいます。
InvalidateRectで再描画を行っているのですが、第3引数をTRUEではドラッグ&ドロップ時の
画像はでるのですが非常にぶれてしまい、FALSEでは画像はぶれないのですが、前の処理が残ってしまい、画像がたくさん出てしまうようになってしまいます。
ドラッグ&ドロップ時に画像をぶれさせずにするようにはできないのでしょうか?
方法を知っている方がいましたら是非教えてください。
以下に現在使ってあるprocを貼らせていただきます。

コード:

#include<windows.h>
#include<olectl.h>
#include <tchar.h>
#include <stdio.h>

HINSTANCE hInst;
HDC hMain;
HBITMAP hBitmap,Bitmap;
BITMAP bitmap;
char str[255];
TCHAR jpeg[3][100] = { "test1.jpg", "test2.jpg", "test4.jpg"} ;
int ii=0;//画像配列の変数
int wx=800;//画面横幅の変数 使うかどうかは未定
int wy=600;//画面縦幅の変数 使うかどうかは未定

int sx=100;
int sy=40;

int xx=0;//座標獲得 ボタンの座標
int yy=0;//座標獲得 ボタンの座標

int xe=0;//LBUTTONUPのときの座標
int ye=0;

int xep1=0;//ドラッグした距離
int yep1=0;

int xep2=0;//ドラッグした距離
int yep2=0;

int flgx=0;
int flgy=0;

int xxx=0;
int yyy=0;

//画像を
void GetHandle1(char File[255],HWND hWnd,HDC hdc){
    
    OLE_HANDLE hOle;
    IStream *iStream=NULL;
    IPicture *iPicture;
    HGLOBAL hMem;
    LPVOID pvData;
    DWORD nReadByte=0,nFileSize;
    HANDLE hFile;
    short type;

    hFile=CreateFile(File,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);//ファイルを開いてハンドル所得
    nFileSize=GetFileSize(hFile,NULL);//ファイルサイズ獲得
    hMem=GlobalAlloc(GMEM_MOVEABLE,nFileSize);//動的メモリの確保
    //GlobalLockを指定してメモリのポインタを返して初めてメモリの確保が終了します。
	pvData=GlobalLock(hMem);
        
    ReadFile(hFile,pvData,nFileSize,&nReadByte,NULL);//↑で確保したメモリにファイルデータ読み込み
	//読み込んだファイルの種類を自動的に判別して展開する関数です

    
    GlobalUnlock(hMem);
    CloseHandle(hFile);
    
    CreateStreamOnHGlobal(hMem,TRUE,&iStream);//ストリームオブジェクト作成
    
    OleLoadPicture(iStream,nFileSize,FALSE,&IID_IPicture,(LPVOID*)&iPicture);
    

//    iStream->lpVtbl->Release(iPicture);
    
    iPicture->lpVtbl->get_Type(iPicture,&type);
    if(type==PICTYPE_BITMAP){
        iPicture->lpVtbl->get_Handle(iPicture,&hOle);
    }
    
    hBitmap=(HBITMAP)hOle;
    
    SelectObject(hMain,hBitmap);
    GetObject(hBitmap,sizeof(BITMAP),&bitmap);
    
}

LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
    PAINTSTRUCT ps;
	static HDC hdc, hCompatDC; 
	static BOOL push=FALSE;//ボタンを押したかによる切り替え

	static TCHAR strScroll[32];
	HRGN hrgn;

	xxx=LOWORD(lParam);
	yyy=HIWORD(lParam);
	
    switch(uMsg){

		case WM_LBUTTONDOWN:	// マウスの左ボタンが押されたときに送られてくる
			xx=LOWORD(lParam);//x座標獲得
			yy=HIWORD(lParam);//y座標獲得
			push=TRUE;
			return 0;
		/*
			BUTTONDOWN=xx
			BUTTONUP  =xe
			ドラッグ&ドロップ
			ボタンダウンしたときの座標と、ボタンアップしたときの座標の差を計算し、
			画像表示時のx,y座標をずらす
			*/

		case WM_LBUTTONUP:
			xe=LOWORD(lParam);//x座標獲得
			ye=HIWORD(lParam);//y座標獲得
			InvalidateRect( hWnd, NULL, TRUE );
			push=FALSE;
		return 0;

		//WM_LBUTTONDOWNでボタンを押している場合のみ起動
		case WM_MOUSEMOVE:
			if(push){
			xe=LOWORD(lParam);//x座標獲得
			ye=HIWORD(lParam);//y座標獲得
			if(xx>xe){//右から左の場合
				xep1=xx-xe;
				flgx=1;
			}else if(xe>xx){//左から右の場合
				xep2=xe-xx;
				flgx=2;
			}

			if(yy>ye){//下から上の場合
				yep1=yy-ye;
				flgy=1;
			}else if(ye>yy){//上から下の場合
				yep2=ye-yy;	
				flgy=2;
			}

			InvalidateRect(hWnd , NULL ,FALSE);
			}
			return 0;


		case WM_CREATE:
			hdc=GetDC(hWnd);
			hMain=CreateCompatibleDC(NULL);
			return 0;

	case WM_PAINT:
			hdc=GetDC(hWnd);
            //hMain=CreateCompatibleDC(NULL);
			
            hdc=BeginPaint(hWnd,&ps);
			TextOut(hdc,10,10,strScroll,lstrlen(strScroll));
			GetHandle1(jpeg[ii],hWnd,hdc);//画像の読み込み
if(flgx==1 && flgy==1){//右から左の場合&&下から上の場合
					StretchBlt( hdc, sx-xep1, sy-yep1,bitmap.bmWidth,bitmap.bmHeight*2,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
			
				}else if(flgx==2 && flgy==1){//左から右の場合&&下から上の場合
					StretchBlt( hdc, sx+xep2, sy-yep1,bitmap.bmWidth,bitmap.bmHeight*2,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
					
				}else if(flgx==1 && flgy==2){//右から左の場合&&上から下の場合
					StretchBlt( hdc, sx-xep1, sy+yep2,bitmap.bmWidth,bitmap.bmHeight*2,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
				
				}else if(flgx==2 && flgy==2){//左から右の場合&&上から下の場合
					StretchBlt( hdc, sx+xep2, sy+yep2,bitmap.bmWidth,bitmap.bmHeight*2,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
					
				}else{//
					StretchBlt( hdc, sx, sy,bitmap.bmWidth*2,bitmap.bmHeight,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
				
				}

			
            EndPaint(hWnd,&ps);
            
            return 0;
		
		case WM_DESTROY:
            DeleteDC(hMain);
            DeleteObject(hBitmap);
            PostQuitMessage(0);
            return 0;
        
    }
    
    return DefWindowProc(hWnd,uMsg,wParam,lParam);
    
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: winapi32での画像ぶれについて

#2

投稿記事 by softya(ソフト屋) » 7年前

動く形で全コードを貼り付けていただくと動作が確認できると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

alulu

Re: winapi32での画像ぶれについて

#3

投稿記事 by alulu » 7年前

以下が全ソースコードとなっています。
本来は他の機能のソースもあるのですが、割愛させていただきます。
以下でも動作するのでご確認下さい。

コード:

#include<windows.h>
#include<olectl.h>
#include <tchar.h>
#include <stdio.h>
 
HINSTANCE hInst;
HDC hMain;
HBITMAP hBitmap,Bitmap;
BITMAP bitmap;
char str[255];
TCHAR jpeg[3][100] = { "test1.jpg", "test2.jpg", "test4.jpg"} ;
int ii=0;//画像配列の変数
int wx=800;//画面横幅の変数 使うかどうかは未定
int wy=600;//画面縦幅の変数 使うかどうかは未定
 
int sx=100;
int sy=40;
 
int xx=0;//座標獲得 ボタンの座標
int yy=0;//座標獲得 ボタンの座標
 
int xe=0;//LBUTTONUPのときの座標
int ye=0;
 
int xep1=0;//ドラッグした距離
int yep1=0;
 
int xep2=0;//ドラッグした距離
int yep2=0;
 
int flgx=0;
int flgy=0;
 
int xxx=0;
int yyy=0;
 
//画像を
void GetHandle1(char File[255],HWND hWnd,HDC hdc){
    
    OLE_HANDLE hOle;
    IStream *iStream=NULL;
    IPicture *iPicture;
    HGLOBAL hMem;
    LPVOID pvData;
    DWORD nReadByte=0,nFileSize;
    HANDLE hFile;
    short type;
 
    hFile=CreateFile(File,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);//ファイルを開いてハンドル所得
    nFileSize=GetFileSize(hFile,NULL);//ファイルサイズ獲得
    hMem=GlobalAlloc(GMEM_MOVEABLE,nFileSize);//動的メモリの確保
    //GlobalLockを指定してメモリのポインタを返して初めてメモリの確保が終了します。
    pvData=GlobalLock(hMem);
        
    ReadFile(hFile,pvData,nFileSize,&nReadByte,NULL);//↑で確保したメモリにファイルデータ読み込み
    //読み込んだファイルの種類を自動的に判別して展開する関数です
 
    
    GlobalUnlock(hMem);
    CloseHandle(hFile);
    
    CreateStreamOnHGlobal(hMem,TRUE,&iStream);//ストリームオブジェクト作成
    
    OleLoadPicture(iStream,nFileSize,FALSE,&IID_IPicture,(LPVOID*)&iPicture);
    
 
//    iStream->lpVtbl->Release(iPicture);
    
    iPicture->lpVtbl->get_Type(iPicture,&type);
    if(type==PICTYPE_BITMAP){
        iPicture->lpVtbl->get_Handle(iPicture,&hOle);
    }
    
    hBitmap=(HBITMAP)hOle;
    
    SelectObject(hMain,hBitmap);
    GetObject(hBitmap,sizeof(BITMAP),&bitmap);
    
}
 
LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
    PAINTSTRUCT ps;
    static HDC hdc, hCompatDC; 
    static BOOL push=FALSE;//ボタンを押したかによる切り替え
 
    static TCHAR strScroll[32];
 
    xxx=LOWORD(lParam);
    yyy=HIWORD(lParam);
    
    switch(uMsg){
 
        case WM_LBUTTONDOWN:    // マウスの左ボタンが押されたときに送られてくる
            xx=LOWORD(lParam);//x座標獲得
            yy=HIWORD(lParam);//y座標獲得
            push=TRUE;
            return 0;
        /*
            BUTTONDOWN=xx
            BUTTONUP  =xe
            ドラッグ&ドロップ
            ボタンダウンしたときの座標と、ボタンアップしたときの座標の差を計算し、
            画像表示時のx,y座標をずらす
            */
 
        case WM_LBUTTONUP:
            xe=LOWORD(lParam);//x座標獲得
            ye=HIWORD(lParam);//y座標獲得
            InvalidateRect( hWnd, NULL, TRUE );
            push=FALSE;
        return 0;
 
        //WM_LBUTTONDOWNでボタンを押している場合のみ起動
        case WM_MOUSEMOVE:
            if(push){
            xe=LOWORD(lParam);//x座標獲得
            ye=HIWORD(lParam);//y座標獲得
            if(xx>xe){//右から左の場合
                xep1=xx-xe;
                flgx=1;
            }else if(xe>xx){//左から右の場合
                xep2=xe-xx;
                flgx=2;
            }
 
            if(yy>ye){//下から上の場合
                yep1=yy-ye;
                flgy=1;
            }else if(ye>yy){//上から下の場合
                yep2=ye-yy; 
                flgy=2;
            }
 
            InvalidateRect(hWnd , NULL ,TRUE);
            }
            return 0;
 
 
        case WM_CREATE:
            hdc=GetDC(hWnd);
            hMain=CreateCompatibleDC(NULL);
            return 0;
 
    case WM_PAINT:
            hdc=GetDC(hWnd);
            //hMain=CreateCompatibleDC(NULL);
            
            hdc=BeginPaint(hWnd,&ps);
            TextOut(hdc,10,10,strScroll,lstrlen(strScroll));
            GetHandle1(jpeg[ii],hWnd,hdc);//画像の読み込み
if(flgx==1 && flgy==1){//右から左の場合&&下から上の場合
                    StretchBlt( hdc, sx-xep1, sy-yep1,bitmap.bmWidth,bitmap.bmHeight,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
            
                }else if(flgx==2 && flgy==1){//左から右の場合&&下から上の場合
                    StretchBlt( hdc, sx+xep2, sy-yep1,bitmap.bmWidth,bitmap.bmHeight,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
                    
                }else if(flgx==1 && flgy==2){//右から左の場合&&上から下の場合
                    StretchBlt( hdc, sx-xep1, sy+yep2,bitmap.bmWidth,bitmap.bmHeight,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
                
                }else if(flgx==2 && flgy==2){//左から右の場合&&上から下の場合
                    StretchBlt( hdc, sx+xep2, sy+yep2,bitmap.bmWidth,bitmap.bmHeight,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
                    
                }else{//
                    StretchBlt( hdc, sx, sy,bitmap.bmWidth,bitmap.bmHeight,hMain, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );
                
                }
 
            
            EndPaint(hWnd,&ps);
            
            return 0;
        
        case WM_DESTROY:
            DeleteDC(hMain);
            DeleteObject(hBitmap);
            PostQuitMessage(0);
            return 0;
        
    }
    
    return DefWindowProc(hWnd,uMsg,wParam,lParam);
    
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR lpCmdLine,int nCmdShow){
    
    HWND hWnd;
    //WNDCLASS wc;
    MSG msg;
	WNDCLASS winc;
    winc.style		= CS_HREDRAW | CS_VREDRAW;
	winc.lpfnWndProc=WindowProc;
	winc.cbClsExtra	= winc.cbWndExtra	= 0;
	winc.hInstance		= hInstance;
	winc.hIcon		= LoadIcon(NULL , IDI_APPLICATION);
	winc.hCursor		= LoadCursor(NULL , IDC_ARROW);
	winc.hbrBackground	= (HBRUSH)GetStockObject(WHITE_BRUSH);
	winc.lpszMenuName	= NULL;
	winc.lpszClassName	= TEXT("abc");

	if (!RegisterClass(&winc)) return -1;

	/*hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("KITTY"), TEXT("Kitty on your lap") ,
                          WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
						  SBS_TOPALIGN | SBS_HORZ | SBS_LEFTALIGN | SBS_VERT | SBS_RIGHTALIGN ,
                          200, 30, wx, wy,NULL,NULL,hInstance, NULL);
	*/
		hWnd = CreateWindow(
			TEXT("abc") , TEXT("window") ,
			WS_OVERLAPPEDWINDOW | WS_VISIBLE|WS_VSCROLL ,
			CW_USEDEFAULT , CW_USEDEFAULT ,
			wx ,wy ,
			NULL , NULL , hInstance , NULL
	);

/*
	hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("KITTY") , TEXT("Kitty on your lap") ,
                          WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER  ,
                          200, 30, wx, wy,NULL,NULL,hInstance, NULL);
	
*/
	if (hWnd == NULL) return -1;

	while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
	return msg.wParam;
}


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: winapi32での画像ぶれについて

#4

投稿記事 by softya(ソフト屋) » 7年前

エラーが出て通りませんので確認お願いします。
1>c:\users\softyasu\documents\visual studio 2008\projects\dxtest\source\main.cpp(64) : error C2664: 'OleLoadPicture' : 4 番目の引数を 'const IID *__w64 ' から 'const IID &' に変換できません。(新しい機能 ; ヘルプを参照)
1> 理由: 'const IID *__w64 ' から 'const IID' へは変換できません。
1> コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。
1>c:\users\softyasu\documents\visual studio 2008\projects\dxtest\source\main.cpp(69) : error C2039: 'lpVtbl' : 'IPicture' のメンバではありません。
1> c:\program files\microsoft sdks\windows\v7.0\include\ocidl.h(3128) : 'IPicture' の宣言を確認してください。
1>c:\users\softyasu\documents\visual studio 2008\projects\dxtest\source\main.cpp(69) : error C2227: '->get_Type' : 左側がクラス、構造体、共用体、ジェネリック型へのポインタではありません。
1>c:\users\softyasu\documents\visual studio 2008\projects\dxtest\source\main.cpp(71) : error C2039: 'lpVtbl' : 'IPicture' のメンバではありません。
1> c:\program files\microsoft sdks\windows\v7.0\include\ocidl.h(3128) : 'IPicture' の宣言を確認してください。
1>c:\users\softyasu\documents\visual studio 2008\projects\dxtest\source\main.cpp(71) : error C2227: '->get_Handle' : 左側がクラス、構造体、共用体、ジェネリック型へのポインタではありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: winapi32での画像ぶれについて

#5

投稿記事 by YuO » 7年前

softya(ソフト屋) さんが書きました:エラーが出て通りませんので確認お願いします。
えーっと,Cでコンパイルするためのコードでは?
# コードはCと書かれていますし。

COMまわりはCとC++で書き方が違うため,C++でコンパイルすればエラーになると思います。
例えば,最初のエラーの元であるREFIIDは,<guiddef.h>で

コード:

#ifdef __cplusplus
#define REFIID const IID &
#else
#define REFIID const IID * __MIDL_CONST
#endif
と定義されています。対応する引数は,Cであれば&IID_IPicture,C++ならばIID_IPictureとなるでしょう。

他にも,COMインターフェースはCではvTable相当を自前で持つ構造体,C++では単純なクラスになります。
そのため,CではlpVtblを経由して関数ポインタを呼び出しますが,C++では通常のメンバ関数呼び出しになります。


でもって,元のコードでは警告がいくつか出たので,まずはそれを潰すところから。
    • 11行目 : warning C4047: '初期化中' : 間接参照のレベルが 'TCHAR' と 'char [10]' で異なっています。
    TCHARに対応するリテラルは,TEXTマクロで囲う必要があります。
    11行目を

    コード:

    TCHAR jpeg[3][100] = { TEXT("test1.jpg"), TEXT("test2.jpg"), TEXT("test4.jpg")} ;
    に変更
    • 49行目 : warning C4133: '関数' : 'char *' と 'LPCWSTR' の間で型に互換性がありません。
    • 150行目 : warning C4133: '関数' : 'TCHAR [100]' と 'char *' の間で型に互換性がありません。
    LPCWSTRというのは,元々はconst TCHAR *であるところ。TCHAR使うのならば,明示的にcharやwchar_tを使う場合を除いて,全てTCHARを使う必要があります。
    38行目を

    コード:

    void GetHandle1(TCHAR File[255],HWND hWnd,HDC hdc){
    に変更
なんとなく,ちらつくのは毎回再描画しているからではないかな,と思ったり。
hMainが全く生かされていないわけですし,必要な領域だけ再描画するなどで,ちらつきは抑えられるかと。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: winapi32での画像ぶれについて

#6

投稿記事 by softya(ソフト屋) » 7年前

失礼しました。main.cに変えてマルチバイト文字でコンパイルして見ました。

確かにチラつきます。WM_PAINTのGetHandle1()で毎回読んでいるのは良くないので、ここで読むのは止めたほうが良いと思います。
それと消去してから書いているのでどうしてもチラつきます。
InvalidateRect(hWnd , NULL ,FALSE);にして裏画面処理するか、新しい場所に移動させてから前のゴミを消去するかどちらかの手を使う必要がありますね。

裏画面処理(ダブル・バッファリング)のサンプル。
「ダブル・バッファリングの方法(1) - プログラミングのメモ帳」
http://blog.goo.ne.jp/masaki_goo_2006/e ... 0e32c83cf5
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

alulu

Re: winapi32での画像ぶれについて

#7

投稿記事 by alulu » 7年前

返信を頂きありがとうございます。
警告文はなくすことが出来ました。
ダブルバッファを頑張って理解してみます。

閉鎖

“C言語何でも質問掲示板” へ戻る