Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перерисовка HBITMAP в окне 
:(
    Опции темы
Count0
Дата 13.7.2016, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 9.7.2016

Репутация: нет
Всего: нет



Доброго времени суток, в ходе разработки небольшой программы для демонстрации графических фильтров возникла следующая проблема:
Есть класс BitImage - Обертка над HBITMAP
Код

#include "hdcmanager.h"
#include "pixel.h"
#include <windows.h>

class BitImage
{
    public:
        inline BitImage()
        {
            m_bIsEmpty = true;
        }
        
        inline BitImage(LPCTSTR lpszName)
        {
            m_hbmpHandle = (HBITMAP) LoadImage( NULL, lpszName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
            BITMAP bmData;
            GetObject(m_hbmpHandle, sizeof(BITMAP), &bmData);
            m_lWidth = bmData.bmWidth;
            m_lHeight = bmData.bmHeight;
            m_bIsEmpty = !m_hbmpHandle;            
        }
        
        inline BitImage(const BitImage& btimPrototype)
        {
            formFromPrototype(btimPrototype);            
        }    
        
        inline BitImage& operator=(const BitImage& btimPrototype)
        {
            clear();
            formFromPrototype(btimPrototype);
            return *this;
        }
        
        inline void Draw(HDC hdcDest, int iXPos, int iYPos)
        {
            HDCManager::instance().freeHDC(m_hbmpHandle);
            HDC hdcService = CreateCompatibleDC(hdcDest);
            HGDIOBJ hgdioDefault = SelectObject(hdcService, m_hbmpHandle);
            BOOL bResult = BitBlt(hdcDest, iXPos, iYPos, m_lWidth, m_lHeight, hdcService, 0,0, SRCCOPY);
            SelectObject(hdcService, hgdioDefault);
            DeleteDC(hdcService);            
        }
        
        inline LONG height() const
        {
            return m_lHeight;
        }
        
        inline LONG width() const
        {
            return m_lWidth;
        }
        
        inline void setPixel(const Pixel& pxlValue, int iX, int iY)
        {
            SetPixel(HDCManager::instance()[m_hbmpHandle], iX, iY, pxlValue.m_clrrValue);
        }
        
        inline Pixel getPixel(int iX, int iY)
        {
            return Pixel(GetPixel(HDCManager::instance()[m_hbmpHandle], iX, iY));
        }
        
        inline ~BitImage()
        {
            clear();
        }
    protected:
        inline void formFromPrototype(const BitImage& btimPrototype)
        {
            m_bIsEmpty = btimPrototype.m_bIsEmpty;
            if(!m_bIsEmpty)
            {
                m_lWidth = btimPrototype.m_lWidth;
                m_lHeight = btimPrototype.m_lHeight;            
                HDC hdcDisplay = HDCManager::instance().baseContext();                
                m_hbmpHandle = CreateCompatibleBitmap(hdcDisplay, m_lWidth, m_lHeight);
                
                HDC hdcSource = CreateCompatibleDC (hdcDisplay);
                HDC hdcDest = CreateCompatibleDC (hdcDisplay);            
                HGDIOBJ hgdioDefaultSource = SelectObject (hdcSource, btimPrototype.m_hbmpHandle);
                HGDIOBJ hgdioDefaultDest = SelectObject (hdcDest, m_hbmpHandle);
                BitBlt (hdcDest, 0, 0, m_lWidth, m_lHeight, hdcSource, 0, 0, SRCCOPY);
                SelectObject (hdcSource, hgdioDefaultSource);
                SelectObject (hdcDest, hgdioDefaultDest);
                DeleteDC (hdcSource); 
                DeleteDC (hdcDest);
            }
        }    
        
        inline void clear()
        {
            HDCManager::instance().freeHDC(m_hbmpHandle);
            if(!m_bIsEmpty)
            {
                DeleteObject(m_hbmpHandle);
                m_bIsEmpty = true;
            }
        }
    protected:
        HBITMAP m_hbmpHandle;
        bool m_bIsEmpty;
        LONG m_lWidth, m_lHeight;
};

Класс HDCManager для хранения HDC, связанного с HBITMA в процессе серии GetPixel/SetPixel:

Код

#include <map>
#include <windows.h>

using namespace std;

class HDCManager
{
    public:
        static inline HDCManager& instance()
        {
            if(s_hdcmInstance == NULL)
            {
                s_hdcmInstance = new HDCManager();
            }
            return *s_hdcmInstance;
        }
        
        inline HDC& operator[](const HBITMAP& hbmpKey)
        {
            map<HBITMAP, pair<HDC, HGDIOBJ> >::iterator it = m_mpContexts.find(hbmpKey);
            if(it == m_mpContexts.end())
            {
                HDC hdcContext = CreateCompatibleDC(m_hdcBase);                
                m_mpContexts.insert(make_pair(hbmpKey, make_pair(hdcContext, SelectObject(hdcContext, hbmpKey))));
                return m_mpContexts.find(hbmpKey)->second.first;
            }
            return it->second.first;
        }
        
        inline HDC& baseContext()
        {
            return m_hdcBase;
        }
        
        inline void freeHDC(const HBITMAP& hbmpFree)
        {
            map<HBITMAP, pair<HDC, HGDIOBJ> >::iterator it = m_mpContexts.find(hbmpFree);
            if(it != m_mpContexts.end())
            {
                SelectObject(it->second.first, it->second.second);
                DeleteDC (it->second.first);
                m_mpContexts.erase(it);
            }
        }
        
        inline ~HDCManager()
        {
            map<HBITMAP, pair<HDC, HGDIOBJ> >::iterator it = m_mpContexts.begin();
            while(it != m_mpContexts.end())
            {
                SelectObject(it->second.first, it->second.second);
                DeleteDC (it->second.first);
                m_mpContexts.erase(it);
                it = m_mpContexts.begin();
            }
            ::ReleaseDC(NULL, m_hdcBase);
        }
        
    protected:
        inline HDCManager()
        {
            m_hdcBase = ::GetDC(NULL);
        }
    protected:
        HDC m_hdcBase;
        map<HBITMAP, pair<HDC, HGDIOBJ> > m_mpContexts;
    private:
        HDCManager(const HDCManager& hdcmPrototype);
        HDCManager& operator=(const HDCManager& hdcmPrototype);
    private:            
        static HDCManager* s_hdcmInstance;
};

HDCManager* HDCManager::s_hdcmInstance = NULL;

Класс Pixel - обертка над COLORREF
Код

#include <windows.h>

class Pixel
{
    friend class BitImage;
    public:
        inline Pixel()
        {
            m_clrrValue = CLR_INVALID;
        }
        inline Pixel(COLORREF clrrValue)
        {
            m_clrrValue = clrrValue;
        }
        inline Pixel(BYTE btRed, BYTE btGreen, BYTE btBlue)
        {
            m_clrrValue = RGB(btRed, btGreen, btBlue);
        }
        inline Pixel(const Pixel& pxlPrototype)
        {
            m_clrrValue = pxlPrototype.m_clrrValue;
        }
        inline BYTE red() const
        {
            return GetRValue(m_clrrValue);
        }
        inline BYTE green() const
        {
            return GetGValue(m_clrrValue);
        }
        inline BYTE blue() const
        {
            return GetBValue(m_clrrValue);
        }
        inline Pixel& operator=(const Pixel& pxlPrototype)
        {
            m_clrrValue = pxlPrototype.m_clrrValue;
            return *this;
        }
        inline ~Pixel()
        {
        }
    protected:
        COLORREF m_clrrValue;
    
};

Ну и собственно код основного окна
Код

#include <windows.h>
#include "bitimage.h"

HMENU hmnNext = (HMENU)1;

BitImage* g_bmiFront;
BitImage* g_bmiBack = NULL;

HWND g_hwndMain;
HINSTANCE hinstGlobal; 

HMENU GetNextElement()
{
    HMENU hmnNew = hmnNext;
    hmnNext++;
    return hmnNew;
}

WNDCLASSEX InitWindow(const LPCTSTR& lstrClassName, LRESULT CALLBACK (*pfWndProc)(HWND, UINT, WPARAM, LPARAM), const HINSTANCE& hInstance, const HBRUSH& hbrBackground,
    const HCURSOR& hcrCursor, const  HICON& hicMain, const HICON& hicMini)
{
    WNDCLASSEX wcNew;
    memset(&wcNew, 0, sizeof(wcNew));
    wcNew.cbSize = sizeof(WNDCLASSEX);
    wcNew.lpszClassName = lstrClassName;
    wcNew.lpfnWndProc = pfWndProc;
    wcNew.hInstance = hInstance;
    wcNew.hbrBackground = hbrBackground;
    wcNew.hCursor = hcrCursor;
    wcNew.hIcon    = hicMain;
    wcNew.hIconSm = hicMini;
    if(!RegisterClassEx(&wcNew)) 
    {
        throw "Îøèáêà ïðè ðåãèñòðàöèè îêíà!";
    }
    return wcNew;
}

HWND SaveCreateWindow(LPCTSTR lstrClassName, LPCTSTR lstrWindowTitle, DWORD dwStyle, int iXPos, int iYPos, int iWidth, int iHeight,    HWND hwndParent, HMENU hmnuBase, HINSTANCE hInstance,
    LPVOID lpvParam)
{
    HWND hwndNew = CreateWindowEx(WS_EX_CLIENTEDGE, lstrClassName, lstrWindowTitle, dwStyle, iXPos, iYPos, iWidth, iHeight, hwndParent, hmnuBase, hInstance, lpvParam);
    if(hwndNew == NULL) 
    {
        throw "Îøèáêà ïðè ñîçäàíèè îêíà!";
    }
    return hwndNew;
}

void ProcessImage(WPARAM wParam)
{
    if(g_bmiBack != NULL)
    {
        delete g_bmiBack;
    }
    g_bmiBack = g_bmiFront;    
    BitImage* bmiTemp = new BitImage(*g_bmiBack);
    for(int iY = 0; iY < bmiTemp->height(); iY++)
    {
        for(int iX = 0; iX < bmiTemp->width(); iX++)
        {
            Pixel pxlCur = g_bmiBack->getPixel(iX, iY);
            bmiTemp->setPixel(Pixel(255 - pxlCur.red(), 255 - pxlCur.green(), 255 - pxlCur.blue()), iX, iY);
        }
    }
    g_bmiFront = bmiTemp;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
    switch(Message) 
    {    
        case WM_CREATE:
        {
            CreateWindow("button", "Îáðàáîòàòü", WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON, 550, 180, 120, 30, hwnd, GetNextElement(), hinstGlobal, NULL);
            break;    
        }
        case WM_COMMAND:
        {
            ProcessImage(wParam);
            RedrawWindow(g_hwndMain, NULL, NULL, RDW_INTERNALPAINT);
            break;
        }
        case WM_PAINT:
        {
            PAINTSTRUCT psImage;
            HDC hdcDisplayContext = BeginPaint(hwnd, &psImage);
            
            g_bmiFront->Draw(hdcDisplayContext, 0, 0);
            
            EndPaint(hwnd, &psImage);
            break;
        }    
        case WM_DESTROY: 
        {
            PostQuitMessage(0);
            break;
        }
        default:
        {
            return DefWindowProc(hwnd, Message, wParam, lParam);
        }            
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{
    MSG msgSystem;
    hinstGlobal = hInstance;
    try
    {        
        g_bmiFront = new BitImage("Lenna.bmp");
        
        LPCTSTR lstrClassName = "ImageFilters";
        HICON hicGeneral = LoadIcon(NULL, IDI_APPLICATION);
        WNDCLASSEX wcMain = InitWindow(lstrClassName, WndProc, hInstance, (HBRUSH)(COLOR_WINDOW+1), LoadCursor(NULL, IDC_ARROW), hicGeneral, hicGeneral); 
        g_hwndMain = SaveCreateWindow(lstrClassName, "Ïðîãðàììà äëÿ îáó÷åíèÿ ïðèìåíåíèþ ãðàôè÷åñêèõ ôèëüòðîâ", WS_VISIBLE|WS_OVERLAPPED|WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 550, 
            NULL, NULL, hInstance, NULL);                    
        while(GetMessage(&msgSystem, NULL, 0, 0) > 0) 
        {
            TranslateMessage(&msgSystem); 
            DispatchMessage(&msgSystem);
        }        
    }
    catch(LPCTSTR lpstrError)
    {
        MessageBox(NULL, lpstrError,"Error!",MB_ICONEXCLAMATION|MB_OK);
    }

    return msgSystem.wParam;
}

Идея текущей версии программы при запуске загружатьи отображать изображение, а по нажатию на кнопку отображать его негатив.
При запуске программы функции отрабатывают корректно  ни одна не возвращает ошибку (проверено отладчиком), однако изображение не изменяется. Что у меня реализовано неправильно? Заранее благодарю.
PS: К сожалению из-за компилятора не могу использовать ни MFC, ни gdi+, так что прошу не предлагать их использовать.

Это сообщение отредактировал(а) Count0 - 13.7.2016, 16:48
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1133 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.