2014-01-08 6 views
0

У меня проблема с установкой атрибутов класса с указателем, вот как выглядит мой код: (эта версия будет компилироваться, но вам нужно открыть окно minesweeper).Ошибка определения атрибута класса с указателем

WindowObject.h: 

#ifndef WINDOWOBJECT_H_INCLUDED 
#define WINDOWOBJECT_H_INCLUDED 

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

class WindowObject 
{ 
public: 
    WindowObject(); 

    BYTE* getPixelMap() const; 
    void setPixelMap(BYTE* bitPointer); 
    void getPixelMap(HWND hwnd); 
private: 
    BYTE* mPixelMap; 
}; 

#endif 

WindowObject.cpp:

#include "WindowObject.h" 

WindowObject::WindowObject() 
{ 
} 

BYTE* WindowObject::getPixelMap() const 
{ 
    printf("getPixelMap: %d\n", mPixelMap[0]); // it crashes, bad pointer!! 
    return mPixelMap; 
} 

void WindowObject::setPixelMap(BYTE *bitPointer) 
{ 
    printf("setPixelMap 1: %d\n", bitPointer[0]); // It works! 
    mPixelMap = bitPointer; 
    printf("setPixelMap 2: %d\n", mPixelMap [0]); // Why does this works and getPixelMap doesn't??? 
} 

void WindowObject::getPixelMap(HWND hwnd) 
{ 
    HDC hdcWindow, hdcMemDC = NULL; 
    HBITMAP hbmScreen = NULL; 
    BITMAP bmpScreen; 

    // Retrieve the handle to a display device context for the client 
    // area of the window. 
    hdcWindow = GetDC(hwnd); 

    // Create a compatible DC which is used in a BitBlt from the window DC 
    hdcMemDC = CreateCompatibleDC(hdcWindow); 

    if(!hdcMemDC) 
    { 
     MessageBoxA(hwnd, "CreateCompatibleDC has failed", "Failed", MB_OK); 
     goto done; 
    } 

    // Get the client area for size calculation 
    RECT rcClient; 
    GetClientRect(hwnd, &rcClient); 

    // Create a compatible bitmap from the Window DC 
    hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top); 

    if(!hbmScreen) 
    { 
     MessageBoxA(hwnd, "CreateCompatibleBitmap Failed", "Failed", MB_OK); 
     goto done; 
    } 

    //Get the BITMAP from the HBITMAP 
    GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen); 

    BITMAPFILEHEADER bmfHeader;  
    BITMAPINFOHEADER bi; 
    BYTE* bitPointer; 

    bi.biSize = sizeof(BITMAPINFOHEADER);  
    bi.biWidth = bmpScreen.bmWidth;  
    bi.biHeight = bmpScreen.bmHeight; 
    bi.biPlanes = 1;  
    bi.biBitCount = 32;  
    bi.biCompression = BI_RGB;  
    bi.biSizeImage = 0; 
    bi.biXPelsPerMeter = 0;  
    bi.biYPelsPerMeter = 0;  
    bi.biClrUsed = 0;  
    bi.biClrImportant = 0; 

    // Create a device independent bitmap that so that we can write to it directly 
    hbmScreen = CreateDIBSection(hdcMemDC, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL); 

    // Select the compatible bitmap into the compatible memory DC. 
    SelectObject(hdcMemDC, hbmScreen); 

    // Bit block transfer into our compatible memory DC. 
    if (!BitBlt(hdcMemDC, 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, hdcWindow, 0, 0, SRCCOPY)) 
    { 
     MessageBox(hwnd, "BitBlt has failed", "Failed", MB_OK); 
     goto done; 
    } 

    // Create PixelMap 
    int width = (rcClient.right-rcClient.left), 
     height = (rcClient.bottom-rcClient.top); 

    printf("Inside getPixelMap: %d\n", bitPointer[0]); // it works! 
    setPixelMap(bitPointer); 

done: 
    DeleteObject(hbmScreen); 
    DeleteObject(hdcMemDC); 
    ReleaseDC(hwnd, hdcWindow); 
} 

main.cpp:

#include "WindowObject.h" 

int main() 
{ 
    WindowObject wObj; 
    HWND hwnd; 

    hwnd = FindWindow(NULL, "Minesweeper"); 

    if (hwnd) 
    { 
     wObj.getPixelMap(hwnd); 
     BYTE* bPointer = wObj.getPixelMap(); 
     printf("After getPixelMap: %d", bPointer[0]); 
    } 
} 

Программа падает, и это дает мне "нарушение прав доступа для чтения местоположения". Я почти на 100% уверен, что проблема возникает из моего указателя, но я нахожу, что он работает на каждом этапе моих тестов, за исключением случаев, когда я получаю его с помощью метода getPixelMap. Любая помощь приветствуется!

+3

Это не скомпилировано. 'bitPointer' не входит в объем этой функции-члена. – chris

+0

Я только дал важную часть своего кода, но не все включено, поэтому он не будет компилироваться, должен ли я публиковать все? Я испугался, что это будет слишком много. – MyUsername112358

+2

Нет, не публикуйте все. Отправьте сообщение [SSCCE] (sscce.org). – juanchopanza

ответ

0

Внутри функции getPixelMap (HWND hwnd) вы вызываете DeleteObject на возвращаемом растровом изображении после сохранения указателя, но перед возвратом. Таким образом, к тому времени, как вы позже получите доступ к растровому изображению, он уже не является допустимым указателем, так как в соответствии с документами CreateDIBSection он говорит, что битмап будет освобожден при вызове DeleteObject.

Вам нужно будет сохранить растровый объект (hbmScreen) и удалить его позже, возможно, в деструкторе.

+0

Он работает! Спасибо огромное! – MyUsername112358

1

Проблема состоит в том, что этот элемент данных либо не инициализирован (если объект класса инициализирован по умолчанию), либо имеет значение 0. Поэтому использование функции-члена getPixelMap() небезопасно. Также, как я думаю, жизнь аргумента функции setPixelMap может быть меньше, чем жизнь объекта класса. Таким образом, поведение программы не определено.

Я думаю, что было бы лучше использовать умный указатель или выделить память для использования самим элементом данных.

Смежные вопросы