質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

563閲覧

WinAPI BITMAPを読み込んでBITMAPの描画・UI

Weapon

総合スコア106

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/04/10 05:47

編集2019/04/14 13:53

前提・実現したいこと

BMPをウィンドウにドロップするとファイルヘッダ―等を読み取って情報を画像とともに表示するコードを書いています.圧縮の有無判別はまだしていませんからかなり荒いですが画像の表示ができません.また文字の表示が一回上書きされてしまいドロップ時に文字列が表示されません. 画像のデータの取得ミスのように思いますがお願いします.

また文字列変数の定義場所や変数の代入方法において改善点がありましたらお願いします.(wsprintfが長くなりすぎている点等)

修正および追記

WM_PAINT周辺は変更したつもりですが223行目のポインターに代入すると例外が投げられます.引数のbitmapのSizeiImageを再代入してみたりしましたが私のデバッグの知識ではそれ以上把握できませんでした.画像の描画領域の確保まではいけていると思いますが画像が表示できません.
GetDCをWM_CREATEで入手していいものかその辺りの変なところもご指摘お願いします.

該当のソースコード

C

1#define UNICODE 2 3#include <windows.h> 4 5LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); 6 7const wchar_t CLASS_NAME[] = L"CLASS"; 8 9HINSTANCE hGlobalInstance; 10 11int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR nCmdLine, _In_ int nCmdShow) { 12 UNREFERENCED_PARAMETER(hPrevInstance); 13 UNREFERENCED_PARAMETER(nCmdLine); 14 15 hGlobalInstance = hInstance; 16 17 WNDCLASSEX wc = { 18 sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, WindowProc, 19 0, 0, hInstance, 20 NULL, (HCURSOR)LoadCursor(NULL, IDC_ARROW), (HBRUSH)GetStockObject(WHITE_BRUSH), 21 NULL, CLASS_NAME, NULL 22 }; 23 24 RegisterClassEx(&wc); 25 26 HWND hwnd = CreateWindowEx( 27 WS_EX_ACCEPTFILES, CLASS_NAME, L"Template", WS_OVERLAPPEDWINDOW, 28 50, 50, 960, 525, 29 NULL, NULL, hInstance, NULL 30 ); 31 32 ShowWindow(hwnd, nCmdShow); 33 UpdateWindow(hwnd); 34 35 MSG msg = {}; 36 37 while (GetMessage(&msg, NULL, 0, 0) > 0) { 38 TranslateMessage(&msg); 39 DispatchMessage(&msg); 40 } 41 42 return (int)msg.wParam; 43} 44 45LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 46 static BOOL status_b_open = FALSE; 47 static DWORD status_d_head = 0; 48 49 static wchar_t filename[_MAX_PATH] = { 0 }; 50 51 static RECT rc = { 0, 0, 0, 0 }; 52 static RECT src = { 5, 5, 0, 0 }; 53 static BITMAPFILEHEADER bmfh; 54 static BITMAPV5HEADER* bmih; 55 56 57 static HDC hdc; 58 static HDC hBuffer; 59 static HBITMAP hbmp; 60 static HANDLE hFile; 61 static HBITMAP bm; 62 63 64 static BYTE* filedata; 65 static void* pv; 66 static wchar_t pstring[4096]; 67 68 switch (uMsg) { 69 case WM_CREATE: 70 hdc = GetDC(hwnd); 71 break; 72 73 case WM_PAINT: 74 { 75 if (status_b_open == TRUE) { 76 if (StretchBlt(hdc, 250, 50, bmih->bV5Width / 2, bmih->bV5Height / 2, hBuffer, 0, 0, bmih->bV5Width, bmih->bV5Height, SRCCOPY) == FALSE) { 77 MessageBox(hwnd, L"Failed to drawtext", L"CAUTION", MB_OK); 78 } 79 } 80 81 DrawText(hdc, pstring, -1, &src, DT_LEFT | DT_TOP); 82 83 ValidateRect(hwnd, NULL); 84 } 85 break; 86 case WM_SIZE: 87 { 88 GetClientRect(hwnd, &rc); 89 src.right = rc.right; 90 src.bottom = rc.bottom; 91 } 92 break; 93 94 95 case WM_DROPFILES: 96 { 97 /* temporary param */ 98 LPDWORD rfsize=0; 99 wchar_t tbmp[64] = { 0 }; 100 wchar_t infoheadstatus[32] = { 0 }; 101 wchar_t getStatus[1025] = { 0 }; 102 /* End temporary param */ 103 104 /* Get Droped File */ 105 wchar_t openedfilename[_MAX_PATH] = { 0 }; 106 wcscpy_s(openedfilename, _MAX_PATH, filename); 107 HDROP hDrop = (HDROP)wParam; 108 unsigned cof = DragQueryFile(hDrop, -1, NULL, 0); 109 if (cof == -1)MessageBox(hwnd, L"This application arrowed only 1 file at the same time", L"CAUTION", MB_OK);//alert when i get plural files -> get the first file 110 DragQueryFile(hDrop, 0, filename, _MAX_PATH); 111 /* End Get Droped File */ 112 113 114 if (wcscmp(filename, openedfilename) != 0) {//process when the droped file is different with before one 115 116 /* Copy File */ 117 hFile = CreateFile(filename, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 118 119 size_t fsize = GetFileSize(hFile, NULL); 120 rfsize = 0; 121 filedata = (BYTE*)malloc(fsize); 122 if (ReadFile(hFile, filedata, fsize, rfsize, NULL) == FALSE) { 123 MessageBox(hwnd, L"FAILED TO READ", L"CAUTION", MB_OK); 124 return -1; 125 } 126 /* End Copy File */ 127 128 /* Get Magic Number */ 129 DWORD dwHead = filedata[0] << 8 | filedata[1]; 130 131 size_t hotspotx = filedata[6] << 8 | filedata[7]; 132 size_t hotspoty = filedata[8] << 8 | filedata[9]; 133 134 DWORD wsize = 0; 135 switch (dwHead) { 136 case 'BM': 137 { 138 int* s = (int*)(filedata + 0xe); 139 if (hotspotx == 0 && hotspoty == 0 && *s != 12) { 140 wsprintf(tbmp, L"BMP file\nBITMAPFILEHEADER : version.1"); 141 status_d_head = 0x100; 142 } 143 else { 144 wsprintf(tbmp, L"BMP file\nBITMAPFILEHEADER : version.2"); 145 status_d_head = 0x200; 146 } 147 148 wsize = filedata[2] | filedata[3] << 8 | filedata[4] << 16 | filedata[5] << 24; 149 } 150 break; 151 152 case 'IC': 153 case 'CI': 154 case 'PT': 155 case 'CP': 156 if (hotspotx != 0 && hotspoty != 0) { 157 wsprintf(tbmp, L"BMP file\nBITMAPFILEHEADER : version.2"); 158 status_d_head = 0x200; 159 wsize = filedata[2] | filedata[3] << 8 | filedata[4] << 16 | filedata[5] << 24; 160 break; 161 } 162 else { 163 wsprintf(tbmp, L"BMP file\nBITMAPFILEHEADER : version.2 but not use hotspot"); 164 status_d_head = 0x200; 165 wsize = 0; 166 break; 167 } 168 default: 169 wsprintf(tbmp, L"not BMP file"); 170 wsize = 0; 171 status_d_head = 0x0; 172 } 173 /* End Get Magic Number */ 174 175 176 /* Check File version and Fill defined structure */ 177 /* Remark : If the file is classified as Bitmap for Windows, i read the file data */ 178 179 180 size_t tableoff = filedata[0xa] | filedata[0xb] << 8 | filedata[0xc] << 16 | filedata[0xd] << 24;//the offset of the table lead from the file lead 181 size_t infosize = filedata[0xe] | filedata[0xf] << 8 | filedata[0x10] << 16 | filedata[0x11] << 24;//size of header 182 183 switch (status_d_head) { 184 case 0x100: 185 { 186 switch (infosize) { 187 case 40: 188 wsprintf(infoheadstatus, L"version.1 for Win"); 189 bmih = (BITMAPV5HEADER*)(filedata + 0xe); 190 wsprintf(getStatus, L"biSize : %d\nbiWidth : %d\nbiHeight : %d\nbiPlanes : %d\nbiBitCount : %d\nbiCompression : %d\nbiSizeImage : %d\nbiXPelsPerMeter : %d\nbiYPelsPerMeter : %d\nbiClrUsed : %d\nbiClrImportant : %d\n\0", bmih->bV5Size, bmih->bV5Width, bmih->bV5Height, bmih->bV5Planes, bmih->bV5BitCount, bmih->bV5Compression, bmih->bV5SizeImage, bmih->bV5XPelsPerMeter, bmih->bV5YPelsPerMeter, bmih->bV5ClrUsed, bmih->bV5ClrImportant); 191 status_d_head |= 0x1; 192 193 break; 194 case 108: 195 wsprintf(infoheadstatus, L"version.4"); 196 bmih = (BITMAPV5HEADER*)(filedata + 0xe); 197 wsprintf(getStatus, L"bV4Size : %d\nbV4Width : %d\nbV4Height : %d\nbV4Planes : %d\nbV4bV4tCount : %d\nbV4Compression : %d\nbV4SizeImage : %d\nbV4XPelsPerMeter : %d\nbV4YPelsPerMeter : %d\nbV4ClrUsed : %d\nbV4ClrImportant : %d\nbV4RedMask : %d\nbV4GreenMask : %d\nbV4BlueMask : %d\nbV4AlphaMask : %d\nbV4CSType : %d\nbV4Endpoints : %p\nbV4GammaRed : %d\nbV4GammaGreen : %d\nbV4GammaBlue : %d\n\0", bmih->bV5Size, bmih->bV5Width, bmih->bV5Height, bmih->bV5Planes, bmih->bV5BitCount, bmih->bV5Compression, bmih->bV5SizeImage, bmih->bV5XPelsPerMeter, bmih->bV5YPelsPerMeter, bmih->bV5ClrUsed, bmih->bV5ClrImportant, bmih->bV5RedMask, bmih->bV5GreenMask, bmih->bV5BlueMask, bmih->bV5AlphaMask, bmih->bV5CSType, bmih->bV5Endpoints, bmih->bV5GammaRed, bmih->bV5GammaGreen, bmih->bV5GammaBlue); 198 status_d_head |= 0x2; 199 200 break; 201 202 case 124: 203 wsprintf(infoheadstatus, L"version.5"); 204 bmih = (BITMAPV5HEADER*)(filedata + 0xe); 205 wsprintf(getStatus, L"bV5Size : %d\nbV5Width : %d\nbV5Height : %d\nbV5Planes : %d\nbV5BitCount : %d\nbV5Compression : %d\nbV5SizeImage : %d\nbV5XPelsPerMeter : %d\nbV5YPelsPerMeter : %d\nbV5ClrUsed : %d\nbV5ClrImportant : %d\nbV5RedMask : %d\nbV5GreenMask : %d\nbV5BlueMask : %d\nbV5AlphaMask : %d\nbV5CSType : %d\nbV5Endpoints : %p\nbV5GammaRed : %d\nbV5GammaGreen : %d\nbV5GammaBlue : %d\nbV5Intent : %d\nbV5ProfileData : %d\nbV5ProfileSize : %d\nbV5Reserved%d\n\0", bmih->bV5Size, bmih->bV5Width, bmih->bV5Height, bmih->bV5Planes, bmih->bV5BitCount, bmih->bV5Compression, bmih->bV5SizeImage, bmih->bV5XPelsPerMeter, bmih->bV5YPelsPerMeter, bmih->bV5ClrUsed, bmih->bV5ClrImportant, bmih->bV5RedMask, bmih->bV5GreenMask, bmih->bV5BlueMask, bmih->bV5AlphaMask, bmih->bV5CSType, (tagICEXYZTRIPLE)bmih->bV5Endpoints, bmih->bV5GammaRed, bmih->bV5GammaGreen, bmih->bV5GammaBlue, bmih->bV5Intent, bmih->bV5ProfileData, bmih->bV5ProfileSize, bmih->bV5Reserved); 206 status_d_head |= 0x3; 207 208 break; 209 210 default: 211 wsprintf(infoheadstatus, L"BROKEN BMP"); 212 213 goto FileCheckEnd; 214 } 215 216 /* Image Rendering */ 217 218 hBuffer = CreateCompatibleDC(hdc); 219 220 hbmp = CreateDIBSection(hBuffer, (BITMAPINFO*)bmih, DIB_RGB_COLORS, &pv, NULL, NULL); 221 if (hbmp != NULL) { 222 int bmpoffset = bmfh.bfOffBits; 223 for (int i = 0; i < bmih->bV5Height * bmih->bV5Width; i++)((unsigned *)pv)[i] = filedata[bmpoffset+i]; 224 225 SelectObject(hBuffer, hbmp); 226 GetObject(hBuffer, sizeof(BITMAP), &bm); 227 228 status_b_open = TRUE; 229 230 } 231 else { 232 MessageBox(hwnd, L"FAILED TO CDIBS", L"CAUTION", MB_OK); 233 status_b_open = FALSE; 234 } 235 236 /* End Image Rendering */ 237 238 239 } 240 break; 241 242 case 0x200: 243 if (infosize == 12) { 244 wsprintf(infoheadstatus, L"core for OS/2"); 245 } 246 else if (infosize >= 16 && infosize <= 64) { 247 wsprintf(infoheadstatus, L"version.2 for OS/2"); 248 } 249 else { 250 wsprintf(infoheadstatus, L"BROKEN BMP for OS/2"); 251 } 252 status_b_open = FALSE; 253 break; 254 255 default: 256 wsprintf(infoheadstatus, L"NO INFOHEADER"); 257 status_b_open = FALSE; 258 } 259 } 260 /* End Check File version and Fill defined structure */ 261 262 /* Pass the string data to the parameter of parent scope */ 263 wsprintf(pstring, L"PATH : %s\n\nFileType : \n%s\n\nInfoHeader : \n%s\n", filename, tbmp, getStatus); 264 /* Pass the string data to the parameter of parent scope */ 265 266 } 267FileCheckEnd: 268 269 InvalidateRect(hwnd, NULL, TRUE); 270 break; 271 272 case WM_DESTROY: 273 PostQuitMessage(0); 274 return 0; 275 } 276 277 return DefWindowProc(hwnd, uMsg, wParam, lParam); 278} 279

補足情報

Windows10 Pro
VisualStudio2019 Community

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2019/04/10 05:54

VisualStudioではソースにブレークポイントを設定して、実行をそこで止め、変数の内容を確認したりできます また、1行づつステップ実行したりできるので、そういうのを使って、まずはご自身でデバッグしていけばどうでしょうか
Weapon

2019/04/10 06:03

確認してみます
episteme

2019/04/10 11:27

200超行にひとつもコメントなしじゃ、あたしゃ読む気にならないね。
Weapon

2019/04/10 14:25

流石にファイルフォーマット頭から読んでるのに関数にもせずそのまま書くのは見にく過ぎました.気を付けます.
yominet

2019/04/10 16:17

WM_PAINTの中身も見直したほうがいい。
atata0319

2019/04/14 17:33

デバッグは知識でやる部分もありますが、最も重要なことは特定タイミングでの変数の値がすべて想定通り(これを一般的には設計通りと言う)であることを確認することです。現在発生している問題はそれだけで解決できます。やり方については y_waiwai さんが既に述べられている通りです。 仕様が決まっているファイルの解析処理は誰が書いても似たようなものになるので、あえてコメントをつけなくても、その知識を持った人には問題はありません。広く意見を募るのであれば、それを知らない人にも読んでもらえるようにコメントを付ける努力は必要です。とは言っても、分かりやすいコメントを付けるには相応の経験は必要ですが。
guest

回答1

0

自己解決

bfOffBitsに正確なオフセットが入ってない場合があるようで0になっていました.
またCreateDIBSectionでシステム作成されたpvBitesの配列が3byte(RGB)で構成されていたため

C

1for (int i = 0; i < bmih->bV5Height * bmih->bV5Width; i++) 2((unsigned*)pv)[i]=filedata[bmpoffset + i]

ではなく

C

1for (int i = 0; i < bmih->bV5Height * bmih->bV5Width * 3; i++) 2((BYTE*)pv)[i]=filedata[bmpoffset + i]

とする必要がありました.

またStretchBltの1/2圧縮表示のサンプリングがうまくいかなかったため直前で

C

1SetStretchBltMode(hdc, STRETCH_HALFTONE);

を呼ぶことで正確に表示できました.

投稿2019/04/15 06:37

Weapon

総合スコア106

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2019/04/15 08:34

本件はもう閉じている上に直接関係も無いのですが、コード中で気づいたので一応指摘させていただきます。 WM_DROPFILESメッセージのハンドリングで、LPDWORD rfsize=0; ... ReadFile(hFile, filedata, fsize, rfsize, NULL) と使っていますが、rfsize は読み出したデータのバイト長を格納するDWORDの変数へのポインタを指定しなければなりません。このコードですとNULLを渡していて、API仕様的には不正です。 ReadFile DWORD lpNumberOfBytesRead https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-readfile This parameter can be NULL only when the lpOverlapped parameter is not NULL. とあるように、NULLがOKなのは、非同期モードでReadFileを呼び出すときだけです。このコードをWindows 7で動作させるとNULLポインターアクセスでエラーが起き、落ちました。質問者さんのWindows10 で問題ないのは、API側のガードが強くなっているのだと思います。
Weapon

2019/04/15 11:28

rfsizeのパラメータがMessageBoxで回収できなかったので不思議に思っていました.ありがとうございます.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問