2016-06-23 2 views
0

Я пытаюсь загрузить растровое изображение в окно, которое я создал. Растровое изображение должно быть фоном окна (я хочу добавить надписи на нем, а затем индикатор прогресса).Как загрузить растровое изображение внутри моего окна?

Это мой код:

HINSTANCE hInst; 
LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
LPSTR lpCmdLine, int nCmdShow) 
{ 
WNDCLASSEX WndCls; 
static WCHAR szAppName[] = L"BitmapIntro"; 
MSG   Msg; 

hInst = hInstance; 
WndCls.cbSize = sizeof(WndCls); 
WndCls.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; 
WndCls.lpfnWndProc = WindProcedure; 
WndCls.cbClsExtra = 0; 
WndCls.cbWndExtra = 0; 
WndCls.hInstance = hInst; 
WndCls.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
WndCls.hCursor = LoadCursor(NULL, IDC_ARROW); 
WndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
WndCls.lpszMenuName = NULL; 
WndCls.lpszClassName = szAppName; 
WndCls.hIconSm = LoadIcon(hInstance, IDI_APPLICATION); 
RegisterClassEx(&WndCls); 

CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, 
    szAppName, 
    L"Bitmaps Fundamentals", 
    WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
    CW_USEDEFAULT, 
    CW_USEDEFAULT, 
    CW_USEDEFAULT, 
    CW_USEDEFAULT, 
    NULL, 
    NULL, 
    hInstance, 
    NULL); 

while (GetMessage(&Msg, NULL, 0, 0)) 
{ 
    TranslateMessage(&Msg); 
    DispatchMessage(&Msg); 
} 

return static_cast<int>(Msg.wParam); 
} 

LRESULT CALLBACK WindProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) 
{ 
HDC hDC, MemDCExercising; 
PAINTSTRUCT Ps; 
HBITMAP bmpExercising; 

switch (Msg) 
{ 
case WM_DESTROY: 
    PostQuitMessage(WM_QUIT); 
    break; 
case WM_PAINT: 

    hDC = BeginPaint(hWnd, &Ps); 

    // Load the bitmap from the resource 
    bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3)); 
    // Create a memory device compatible with the above DC variable 
    MemDCExercising = CreateCompatibleDC(hDC); 
    // Select the new bitmap 
    SelectObject(MemDCExercising, bmpExercising); 

    // Copy the bits from the memory DC into the current dc 
    BitBlt(hDC, 10, 10, 450, 400, MemDCExercising, 0, 0, SRCCOPY); 

    // Restore the old bitmap 
    DeleteDC(MemDCExercising); 
    DeleteObject(bmpExercising); 
    EndPaint(hWnd, &Ps); 
    break; 
default: 
    return DefWindowProc(hWnd, Msg, wParam, lParam); 
} 
return 0; 
} 

Проблема заключается в том, размер PNG мал по сравнению с окном, поэтому при открытии PNG, она занимает только левый высокий угол. Как я могу растянуть его размер окна или хотя бы нарисовать его снова и снова, пока он не заполнит окно?

+0

[StretchBlt] (https://msdn.microsoft.com/en-us/library/dd145120.aspx). Включая все уродливые артефакты и ухудшение качества. – IInspectable

ответ

2

Как я могу сделать это растянуть мой размер окна

Использование StretchBlt() вместо BitBlt().

case WM_PAINT: 
{  
    // Get the window dimensions 
    RECT r; 
    GetClientRect(hWnd, &r); 

    // Load the bitmap from the resource 
    HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3)); 

    // Get the bitmap dimensions 
    BITMAP bmp; 
    GetObject(bmpExercising, sizeof(BITMAP), &bmp); 

    PAINTSTRUCT Ps; 
    HDC hDC = BeginPaint(hWnd, &Ps); 

    // Create a memory device compatible with the above DC variable 
    HDC MemDCExercising = CreateCompatibleDC(hDC); 

    // Select the new bitmap 
    HBITMAP hOldBmp = SelectObject(MemDCExercising, bmpExercising); 

    // Copy the bits from the memory DC into the current dc 
    StretchBlt(hDC, 0, 0, r.right - r.left, r.bottom - r.top, MemDCExercising, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); 

    // Restore the old bitmap 
    SelectObject(MemDCExercising, hOldBmp); 

    // Destroy the memory device 
    DeleteDC(MemDCExercising); 

    // Destroy the bitmap 
    DeleteObject(bmpExercising); 

    EndPaint(hWnd, &Ps); 
    break; 
} 

или по крайней мере сделать это снова и снова, пока она не заполнит окно?

Существует два разных способа обработки этого.

  1. при запуске, загрузке растрового изображения и создать HBRUSH вокруг него с помощью CreatePatternBrush(), а затем присвоить, что в WNDCLASS::hbrBackground поле при регистрации класса окна. Позвольте ОС нарисовать фон окна, используя растровое изображение для вас.

    HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3)); 
    WndCls.hbrBackground = CreatePatternBrush(bmpExercising); 
    
  2. , если вы хотите, чтобы нарисовать битмап вручную, имеет свою краску обработчик вызова BitBlt() через пару петель. Вы знаете размеры растрового изображения (которые вы можете получить в коде с помощью GetObject() и структуры BITMAP), и вы знаете размеры окна (которое вы можете получить в коде с помощью GetWindowRect() или GetClientRect()). Поэтому просто рисуйте одно и то же растровое изображение более одного раза при разных смещениях по мере необходимости. Начните с рисования его один раз в верхнем левом углу, затем переместите правые пиксели ширины растрового изображения и снова нарисуйте его, повторяя, пока вы не перейдете за пиксели ширины окна. Затем переместите влево назад на 0 и переместите пиксели высотой растрового изображения и снова повторите всю ширину линии, повторяя, пока вы не перейдете за пиксели высоты окна.

    case WM_PAINT: 
    {  
        // Get the window dimensions 
        RECT r; 
        GetClientRect(hWnd, &r); 
    
        // Load the bitmap from the resource 
        HBITMAP bmpExercising = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3)); 
    
        // Get the bitmap dimensions 
        BITMAP bmp; 
        GetObject(bmpExercising, sizeof(BITMAP), &bmp); 
    
        PAINTSTRUCT Ps; 
        HDC hDC = BeginPaint(hWnd, &Ps); 
    
        // Create a memory device compatible with the above DC variable 
        HDC MemDCExercising = CreateCompatibleDC(hDC); 
    
        // Select the new bitmap 
        HBITMAP hOldBmp = SelectObject(MemDCExercising, bmpExercising); 
    
        int width = r.right - r.left; 
        int height = r.bottom - r.top; 
    
        // Copy the bits from the memory DC into the current dc 
        for(int y = 0; y < height; y += bmp.bmHeight) 
        { 
         for(int x = 0; x < width; x += bmp.bmWidth) 
         { 
          BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, MemDCExercising, 0, 0, SRCCOPY); 
         } 
        } 
    
        // Restore the old bitmap 
        SelectObject(MemDCExercising, hOldBmp); 
    
        // Destroy the memory device 
        DeleteDC(MemDCExercising); 
    
        // Destroy the bitmap 
        DeleteObject(bmpExercising); 
    
        EndPaint(hWnd, &Ps); 
        break; 
    } 
    

Теперь, с учетом сказанного, вот некоторые дополнительные примечания:

  1. вы не должны быть в загрузке изображения внутри обработчика краски. Загрузите его один раз перед созданием окна, а затем повторно используйте один и тот же HBITMAP для каждой операции рисования до тех пор, пока окно не будет уничтожено, а затем освободите растровое изображение.

  2. LoadBitmap() устарела, вы должны использовать LoadImage() вместо этого, например:

    HBITMAP bmpExercising = (HBITMAP) LoadImage(hInst, MAKEINTRESOURCE(IDB_BITMAP3), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 
    
  3. вы сказали, «Точечный рисунок должен быть фон окна», так что вы должны быть рисование растрового изображения в ответ на вместо сообщения WM_PAINT.

    case WM_ERASEBKGND: 
    {  
        HDC hDC = (HDC) wParam; 
    
        // draw the bitmap on hDC as needed... 
    
        return 1; 
    } 
    
Смежные вопросы