背景としてビットマップを使用している Windows XP で所有者が描画したボタンで、ビットマップが正しく表示されないという断続的な問題が発生しています。ボタンの背景に使用されるビットマップ イメージに同じビットマップ ファイルを使用している複数のボタンを含むウィンドウが表示され、ほとんどのボタンが正しく表示されます。小さいサイズ。
アプリケーションを終了してから再起動すると、ボタンのアイコンが正しく表示されないという同じ動作が見られる場合がありますが、以前と同じボタンである場合とそうでない場合があります。また、ボタン上のアイコンが正しく表示されないというこの動作は、常に見られるわけではありません。表示される場合と表示されない場合があります。ボタンのアイコンをロードすると、それを保持するだけなので、ボタンが正しく表示されないと、常に正しく表示されなくなります。
GetObject()
デバッガーを使用して、最終的に、関数が呼び出されたときにビットマップ サイズに対して返されるデータが正しくないことがあることがわかりました。たとえば、あるケースでは、ビットマップが 75x75 ピクセルで、返されるサイズGetObject()
が 13x13 でした。このサイズはビットマップの描画の一部として使用されるため、表示される背景はボタン ウィンドウの小さな装飾になります。
実際のソース領域は次のとおりです。
if (!hBitmapFocus) {
CString iconPath;
iconPath.Format(ICON_FILES_DIR_FORMAT, m_Icon);
hBitmapFocus = (HBITMAP)LoadImage(NULL, iconPath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
if (hBitmapFocus) {
BITMAP bitmap;
int iNoBytes = GetObject(hBitmapFocus, sizeof(BITMAP), &bitmap);
if (iNoBytes < 1) {
char xBuff[128];
sprintf (xBuff, "GetObject() failed. GetLastError = %d", GetLastError ());
NHPOS_ASSERT_TEXT((iNoBytes > 0), xBuff);
}
cxSource = bitmap.bmWidth;
cySource = bitmap.bmHeight;
//Bitmaps cannot be drawn directly to the screen so a
//compatible memory DC is created to draw to, then the image is
//transfered to the screen
CDC hdcMem;
hdcMem.CreateCompatibleDC(pDC);
HGDIOBJ hpOldObject = hdcMem.SelectObject(hBitmapFocus);
int xPos;
int yPos;
//The Horizontal and Vertical Alignment
//For Images
//Are set in the Layout Manager
//the proper attribute will have to be checked against
//for now the Image is centered on the button
//Horizontal Alignment
if(btnAttributes.horIconAlignment == IconAlignmentHLeft){//Image to left
xPos = 2;
}else if(btnAttributes.horIconAlignment == IconAlignmentHRight){//Image to right
xPos = myRect.right - cxSource - 5;
}else {//Horizontal center
xPos = ((myRect.right - cxSource) / 2) - 1;
}
//Vertical Alignment
if(btnAttributes.vertIconAlignment == IconAlignmentVTop){//Image to top
yPos = 2;
}else if(btnAttributes.vertIconAlignment == IconAlignmentVBottom){//Image to bottom
yPos = myRect.bottom - cySource - 5;
}else{//Vertical Center
yPos = ((myRect.bottom - cySource) / 2) - 1;
}
pDC->BitBlt(xPos, yPos, cxSource, cySource, &hdcMem, 0, 0, SRCCOPY);
hdcMem.SelectObject(hpOldObject);
}
デバッガーを使用すると、iconPath
文字列が正しく、ビットマップが読み込まれてhBitmapFocus
NULL ではないことがわかります。GetObject()
次に、 への呼び出しが行われ、返される値iNoBytes
が 24 に等しいことがわかります。値が正しく表示されるボタンの場合は正しいですがbitmap.bmWidth
、値が表示されないボタンのbitmap.bmHeight
場合、値が小さすぎて、描画時にサイズが正しくありません。ビットマップ。
変数は、クラス ヘッダーで次のように定義されます。
HBITMAP hBitmapFocus;
これに関する調査の一環として、このスタック オーバーフローの質問を見つけました。GetObject は奇妙なサイズを返します。ここに何らかのアライメントの問題があるかどうか疑問に思っています。
bitmap
呼び出しで使用される変数は、GetObject()
何らかのアライメント境界上にある必要がありますか? データの一部にパックを使用している間、pragma
ディレクティブを使用して、1 バイト境界でパックする必要があるインクルード ファイル内の特定の構造体を含むコードの特定の部分のみを指定しています。