Ir ao conteúdo

C Imprimir .bmp com transparência? Windows API


Ir à solução Resolvido por arfneto,

Posts recomendados

Postado

Boa tarde a todos.

Estava tentando imprimir um .bmp quando apertado um botão, só que essa imagem teria que ter transparência.

Não sei como faria senão mudar a cor de cada pixel. Esse .bmp estaria na frente de outro, então o que eu queria fazer é pegar a cor dos pixels do .bmp de trás e pintar o fundo do .bmp da frente.

Isso daria pra ser feito, considerando que o fundo do .bmp é branco, apenas identificando se um pixel é branco e trocando a cor dele.

Porém, não obtive sucesso ao tentar fazer isso, agradeço a todos pela ajuda desde já.

// Essa função não é minha!
// O encontrei aqui: https://www.codeproject.com/Articles/2841/How-to-replace-a-color-in-a-HBITMAP
// Não estou publicando a minha versão editada porque não deu certo e está uma bagunça

#define COLORREF2RGB(Color) (Color & 0xff00) | ((Color >> 16) & 0xff) \
                                 | ((Color << 16) & 0xff0000)

//-------------------------------------------------------------------------------
// ReplaceColor
//
// Author    : Dimitri Rochette [email protected]
// Specials Thanks to Joe Woodbury for his comments and code corrections
//
// Includes  : Only <windows.h>

//
// hBmp         : Source Bitmap
// cOldColor : Color to replace in hBmp
// cNewColor : Color used for replacement
// hBmpDC    : DC of hBmp ( default NULL ) could be NULL if hBmp is not selected
//
// Retcode   : HBITMAP of the modified bitmap or NULL for errors
//
//-------------------------------------------------------------------------------
HBITMAP ReplaceColor(HBITMAP hBmp,COLORREF cOldColor,COLORREF cNewColor,HDC hBmpDC)
{
    HBITMAP RetBmp=NULL;
    if (hBmp)
    {
        HDC BufferDC=CreateCompatibleDC(NULL);    // DC for Source Bitmap
        if (BufferDC)
        {
            HBITMAP hTmpBitmap = (HBITMAP) NULL;
            if (hBmpDC)
                if (hBmp == (HBITMAP)GetCurrentObject(hBmpDC, OBJ_BITMAP))
            {
                hTmpBitmap = CreateBitmap(1, 1, 1, 1, NULL);
                SelectObject(hBmpDC, hTmpBitmap);
            }

            HGDIOBJ PreviousBufferObject=SelectObject(BufferDC,hBmp);
            // here BufferDC contains the bitmap

            HDC DirectDC=CreateCompatibleDC(NULL); // DC for working
            if (DirectDC)
            {
                // Get bitmap size
                BITMAP bm;
                GetObject(hBmp, sizeof(bm), &bm);

                // create a BITMAPINFO with minimal initilisation 
                // for the CreateDIBSection
                BITMAPINFO RGB32BitsBITMAPINFO; 
                ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
                RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
                RGB32BitsBITMAPINFO.bmiHeader.biWidth=bm.bmWidth;
                RGB32BitsBITMAPINFO.bmiHeader.biHeight=bm.bmHeight;
                RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;
                RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32;

                // pointer used for direct Bitmap pixels access
                UINT * ptPixels;    

                HBITMAP DirectBitmap = CreateDIBSection(DirectDC, 
                                       (BITMAPINFO *)&RGB32BitsBITMAPINFO, 
                                       DIB_RGB_COLORS,
                                       (void **)&ptPixels, 
                                       NULL, 0);
                if (DirectBitmap)
                {
                    // here DirectBitmap!=NULL so ptPixels!=NULL no need to test
                    HGDIOBJ PreviousObject=SelectObject(DirectDC, DirectBitmap);
                    BitBlt(DirectDC,0,0,
                                   bm.bmWidth,bm.bmHeight,
                                   BufferDC,0,0,SRCCOPY);

                       // here the DirectDC contains the bitmap

                    // Convert COLORREF to RGB (Invert RED and BLUE)
                    cOldColor=COLORREF2RGB(cOldColor);
                    cNewColor=COLORREF2RGB(cNewColor);

                    // After all the inits we can do the job : Replace Color
                    for (int i=((bm.bmWidth*bm.bmHeight)-1);i>=0;i--)
                    {
                        if (ptPixels[i]==cOldColor) ptPixels[i]=cNewColor;
                    }
                    // little clean up
                    // Don't delete the result of SelectObject because it's 
                    // our modified bitmap (DirectBitmap)
                       SelectObject(DirectDC,PreviousObject);

                    // finish
                    RetBmp=DirectBitmap;
                }
                // clean up
                DeleteDC(DirectDC);
            }            
            if (hTmpBitmap)
            {
                SelectObject(hBmpDC, hBmp);
                DeleteObject(hTmpBitmap);
            }
            SelectObject(BufferDC,PreviousBufferObject);
            // BufferDC is now useless
            DeleteDC(BufferDC);
        }
    }
    return RetBmp;
}

Fui editando a função acima, mas não obtive sucesso...

Eu a chamo da seguinte forma:

void LoadMyImage3(void) {

    hBitmap3 = (HBITMAP) LoadImage(NULL, "hitmarker.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
  	//Ele apenas troca branco por preto nesse caso:
    hBitmap3 = ReplaceColor(hBitmap3, RGB(255, 255, 255), RGB(0, 0, 0), NULL);
  	//Ainda não é o que quero, tentei editar a função mas não deu certo...
    if(hBitmap3 == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}

image.png.7cba7548ca85f3eb5356ae0546ec0e65.png

Vou anexar os .bmp's. O .bmp do fundo é o antvirus.bmp, e o da frente, hitmarker.bmp.

 

hitmarker.bmp antvirus.bmp

  • Curtir 2
Postado

Eu tentei fazer, mas ainda to aprendendo...

Alguém poderia ajudar?

//...
HBITMAP hBitmap;
HBITMAP hBitmap3;
POINT posicao;
//...
void LoadMyImage(void) {

    hBitmap = (HBITMAP) LoadImage(NULL, "antvirus.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(hBitmap == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}
//...
void LoadMyImage3(void) {

    hBitmap3 = (HBITMAP) LoadImage(NULL, "hitmarker.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(hBitmap3 == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}

#define COLORREF2RGB(Color) (Color & 0xff00) | ((Color >> 16) & 0xff) \
                                 | ((Color << 16) & 0xff0000)

HBITMAP ReplaceColor(HBITMAP hBmp,COLORREF cOldColor,HDC hBmpDC)
{
    HBITMAP RetBmp=NULL;
    HBITMAP RetBmp2=NULL;
    if (hBmp && hBitmap)
    {
        HDC BufferDC=CreateCompatibleDC(NULL);    // DC for Source Bitmap
        HDC BufferDC2=CreateCompatibleDC(NULL);    // DC for Source Bitmap
        if (BufferDC && BufferDC2)
        {
            HBITMAP hTmpBitmap = (HBITMAP) NULL;
            HBITMAP hTmpBitmap2 = (HBITMAP) NULL;
            if (hBmpDC){
                if (hBmp == (HBITMAP)GetCurrentObject(hBmpDC, OBJ_BITMAP))
                {
                    hTmpBitmap = CreateBitmap(1, 1, 1, 1, NULL);
                    SelectObject(hBmpDC, hTmpBitmap);
                } else if (hBitmap == (HBITMAP)GetCurrentObject(hBmpDC, OBJ_BITMAP))
                {
                    hTmpBitmap2 = CreateBitmap(1, 1, 1, 1, NULL);
                    SelectObject(hBmpDC, hTmpBitmap2);
                }
            }

            HGDIOBJ PreviousBufferObject=SelectObject(BufferDC,hBmp);
            HGDIOBJ PreviousBufferObject2=SelectObject(BufferDC2,hBitmap);
            // here BufferDC contains the bitmap

            HDC DirectDC=CreateCompatibleDC(NULL); // DC for working
            HDC DirectDC2=CreateCompatibleDC(NULL); // DC for working
            if (DirectDC && DirectDC2)
            {
                // Get bitmap size
                BITMAP bm, bm2;
                GetObject(hBmp, sizeof(bm), &bm);

                // create a BITMAPINFO with minimal initilisation
                // for the CreateDIBSection
                BITMAPINFO RGB32BitsBITMAPINFO;
                ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
                RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
                RGB32BitsBITMAPINFO.bmiHeader.biWidth=bm.bmWidth;
                RGB32BitsBITMAPINFO.bmiHeader.biHeight=bm.bmHeight;
                RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;
                RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32;

                GetObject(hBitmap, sizeof(bm2), &bm2);

                // create a BITMAPINFO with minimal initilisation
                // for the CreateDIBSection
                BITMAPINFO RGB32BitsBITMAPINFO2;
                ZeroMemory(&RGB32BitsBITMAPINFO2,sizeof(BITMAPINFO));
                RGB32BitsBITMAPINFO2.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
                RGB32BitsBITMAPINFO2.bmiHeader.biWidth=bm2.bmWidth;
                RGB32BitsBITMAPINFO2.bmiHeader.biHeight=bm2.bmHeight;
                RGB32BitsBITMAPINFO2.bmiHeader.biPlanes=1;
                RGB32BitsBITMAPINFO2.bmiHeader.biBitCount=32;

                // pointer used for direct Bitmap pixels access
                UINT * ptPixels;
                UINT * ptPixels2;

                HBITMAP DirectBitmap = CreateDIBSection(DirectDC,
                                       (BITMAPINFO *)&RGB32BitsBITMAPINFO,
                                       DIB_RGB_COLORS,
                                       (void **)&ptPixels,
                                       NULL, 0);
                HBITMAP DirectBitmap2 = CreateDIBSection(DirectDC2,
                                       (BITMAPINFO *)&RGB32BitsBITMAPINFO2,
                                       DIB_RGB_COLORS,
                                       (void **)&ptPixels2,
                                       NULL, 0);
                if (DirectBitmap && DirectBitmap2)
                {
                    // here DirectBitmap!=NULL so ptPixels!=NULL no need to test
                    HGDIOBJ PreviousObject=SelectObject(DirectDC, DirectBitmap);
                    BitBlt(DirectDC,0,0,
                                   bm.bmWidth,bm.bmHeight,
                                   BufferDC,0,0,SRCCOPY);

                    HGDIOBJ PreviousObject2=SelectObject(DirectDC2, DirectBitmap2);
                    GetCursorPos(&posicao);
                    int x = posicao.x;
                    int y = posicao.y;
                    BitBlt(DirectDC2,0,0,
                                   bm2.bmWidth,bm2.bmHeight,
                                   BufferDC2,x,y,SRCCOPY);

                       // here the DirectDC contains the bitmap

                    // Convert COLORREF to RGB (Invert RED and BLUE)
                    cOldColor=COLORREF2RGB(cOldColor);

                    // After all the inits we can do the job : Replace Color
                    for (int i=((bm.bmWidth*bm.bmHeight)-1), j=((bm2.bmWidth*bm2.bmHeight)-1);i>=0;i--, j--)
                    {
                        if (ptPixels[i]==cOldColor) ptPixels[i]=ptPixels2[j];
                    }
                    // little clean up
                    // Don't delete the result of SelectObject because it's
                    // our modified bitmap (DirectBitmap)
                    SelectObject(DirectDC,PreviousObject);
                    // finish
                    RetBmp=DirectBitmap;

                    SelectObject(DirectDC2,PreviousObject2);
                    // finish
                    RetBmp2=DirectBitmap2;
                }
                // clean up
                DeleteDC(DirectDC);
                DeleteDC(DirectDC2);
            }
            if (hTmpBitmap && hTmpBitmap2)
            {
                SelectObject(hBmpDC, hBmp);
                DeleteObject(hTmpBitmap);
                SelectObject(hBmpDC, hBitmap);
                DeleteObject(hTmpBitmap2);
            }
            SelectObject(BufferDC,PreviousBufferObject);
            DeleteDC(BufferDC);
            SelectObject(BufferDC2,PreviousBufferObject2);
            DeleteDC(BufferDC2);
        }
    }
    return RetBmp;
}
//...

 

  • Curtir 1
Postado

@Lucca Rodrigues assim o console fica transparente

#include <iostream>
#define _WIN32_WINNT 0x0500
#include <windows.h>
using namespace std;
int main()
{
    HWND hWnd = GetConsoleWindow();
    SetConsoleTitle("Test");
    SetWindowLong(hWnd, GWL_EXSTYLE,
    GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    SetLayeredWindowAttributes(hWnd, 0, 50, LWA_ALPHA);
    system("PAUSE");
    return 0;
}

 

  • Curtir 1
  • Obrigado 1
Postado
16 horas atrás, Lucca Rodrigues disse:

Então... Por isso mesmo eu tava tentando editar aquela função.

Seria de certa forma uma "transparência". Só seriam trocados os pixels do fundo do .bmp pelos do .bmp atrás.

 

Não há razão para não funcionar.

 

O formato está descrito com algum detalhe aqui
 https://docs.microsoft.com/en-us/windows/win32/gdi/bitmap-storage

 

	struct FileHeader
	{
		char header[2]{ 'B', 'M' };
		int32_t fileSize;
		int32_t reserved{ 0 };
		int32_t dataOffset;
	};

	struct InfoHeader
	{
		int32_t	headerSize{ 40 };
		int32_t	width;
		int32_t	height;
		int16_t	planes{ 1 };
		int16_t	bitsPerPixel{ 24 };
		int32_t	compression{ 0 };
		int32_t	dataSize{ 0 };
		int32_t	horizontalResolution{ 2400 };
		int32_t	verticalResolution{ 2400 };
		int32_t	colors{ 0 };
		int32_t	importantColors{ 0 };
	};

Essas são possíveis declarações do início do arquivo. Logo a seguir vem os pixels, uma linha por vez.

  • Curtir 1
  • Obrigado 1
Postado

@arfneto Eu tentei me basear em vários exemplos, como esse e esse, que encontrei por aí.

Acho que o certo seria usar a função transparentblt(). Todavia, não obtive sucesso ao aplicá-la, a imagem permaneceu inalterada.

No caso, quando o botão fosse apertado (case WM_COMMAND), essa função teria que ser aplicada.

Meu programa:

#define _WIN32_WINNT 0x0500  /* tem ficar na primeira linha do código */
#define WINVER 0x0600
#include <windows.h>
#include <wingdi.h>

#define WM_CREATE 0x0001
#define WM_DESTROY 0x0002

#define ID_IMAGE1 1
#define ID_IMAGE2 2
#define ID_IMAGE3 3

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void LoadMyImage(void);
void LoadMyImage2(void);
void LoadMyImage3(void);

HBITMAP hBitmap;
HBITMAP hBitmap2;
HBITMAP hBitmap3;
POINT posicao;
int x, y;
HWND hWnd = GetConsoleWindow();

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR lpCmdLine, INT nCmdShow) {

    MSG  msg;
    WNDCLASSW wc = {0};
    wc.lpszClassName = L"Static image";
    wc.hInstance     = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc   = WndProc;
    wc.hCursor       = LoadCursor(0,IDC_ARROW);


    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"MLG antivirus",
                  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                  100, 100, 1001, 601, 0, 0, hInstance, 0);

    ShowWindow(hWnd, SW_MINIMIZE);
    //won't hide the window without SW_MINIMIZE
    ShowWindow(hWnd, SW_HIDE);

    while (GetMessage(&msg, NULL, 0, 0)) {

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
    WPARAM wParam, LPARAM lParam) {

    HWND hsti;
    HWND hBitmapButton;
    HWND hitm;

    switch(msg) {

        case WM_CREATE:

            LoadMyImage();
            hsti = CreateWindowW(L"Static", L"",
                WS_CHILD | WS_VISIBLE | SS_BITMAP,
                0, 0, 300, 300, hwnd, (HMENU) ID_IMAGE1, NULL, NULL);

            SendMessage(hsti, STM_SETIMAGE,
                (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap);

            LoadMyImage2();
            hBitmapButton = CreateWindowW(L"BUTTON", L"", WS_CHILD | WS_VISIBLE
                | BS_PUSHBUTTON | BS_BITMAP,
                334, 291, 316, 136, hwnd, (HMENU)ID_IMAGE2, NULL, NULL);

            SendMessage(hBitmapButton, BM_SETIMAGE,
                (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap2);
            break;

        case WM_COMMAND:

            if (LOWORD(wParam) == ID_IMAGE2) {
                GetCursorPos(&posicao);
                x = posicao.x-127;
                y = posicao.y-150;

                LoadMyImage3();
              	//O fundo da imagem teria que ser transparente
                hitm = CreateWindowW(L"Static", L"",
                    WS_CHILD | WS_VISIBLE | SS_BITMAP,
                    x, y, 38, 38, hwnd, (HMENU) ID_IMAGE3, NULL, NULL);

                SendMessage(hitm, STM_SETIMAGE,
                    (WPARAM) IMAGE_BITMAP, (LPARAM) hBitmap3);

                Sleep(80);
                DeleteObject((HBITMAP)hBitmap3);
            }

            break;

        case WM_DESTROY:

            DeleteObject((HBITMAP)hBitmap);
            DeleteObject((HBITMAP)hBitmap2);
            PostQuitMessage(0);
            PostMessage(hWnd, WM_CLOSE, 0, 0);
            break;
    }

    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void LoadMyImage(void) {

    hBitmap = (HBITMAP) LoadImage(NULL, "antvirus.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(hBitmap == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}

void LoadMyImage2(void) {

    hBitmap2 = (HBITMAP) LoadImage(NULL, "botao.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(hBitmap2 == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}

void LoadMyImage3(void) {

    hBitmap3 = (HBITMAP) LoadImage(NULL, "hitmarker.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if(hBitmap3 == NULL){
        MessageBox(NULL, "Error while loading image", "Error", MB_OK|MB_ICONERROR);
    }
}

 

  • Curtir 1
Postado
2 horas atrás, Lucca Rodrigues disse:

Eu tentei me basear em vários exemplos, como esse e esse, que encontrei por aí.

Acho que o certo seria usar a função transparentblt(). Todavia, não obtive sucesso ao aplicá-la, a imagem permaneceu inalterada.

 

Teste isso em separado, se ainda não o fez. Apenas rode as funções e crie os bitmaps no micro

  • Curtir 1
  • Obrigado 1
Postado

@arfneto Uma dúvida...

Eu consigo carregar a imagem quando WM_PAINT é chamado, o que eu teria que fazer para adaptar isso quando WM_COMMAND for chamado?

Código:

case WM_PAINT:
    {
        PAINTSTRUCT ps;
        POINT posicao;
        HDC hdc = BeginPaint(hwnd, &ps);
        HDC memdc = CreateCompatibleDC(hdc);
        HDC dcSkin = CreateCompatibleDC(hdc);
        LoadMyImage();
        LoadMyImage3();
        HBITMAP hOldMemBmp = (HBITMAP)SelectObject(memdc, hBitmap);
        HBITMAP hOldSkinBmp = (HBITMAP)SelectObject(dcSkin, hBitmap3);
      	//Carregar a imagem onde o cursor do mouse está
        GetCursorPos(&posicao);
        x = posicao.x-127;
        y = posicao.y-150;
        TransparentBlt(memdc, x, y, 38,38, dcSkin, 0, 0, 38, 38, RGB(255, 255, 255));
        BitBlt(hdc, 0, 0, 988, 562, memdc, 0, 0, SRCCOPY);
        DeleteObject(hOldSkinBmp);
        DeleteObject(hOldMemBmp);
        DeleteDC(memdc);
        DeleteDC(dcSkin);
        EndPaint(hwnd, &ps);
    }
    break;

Nesse caso, TransparentBlt() funcionou, eu tenho uma imagem com "transparência".

  • Curtir 1
Postado

@arfneto Nesse programa aí, eu só chamo WM_CREATE, WM_COMMAND e WM_DESTROY. O bitmap de fundo e o botão são carregados no WM_CREATE. No caso eu precisaria mesmo carregar a imagem quando WM_COMMAND fosse chamado, mas se eu uso o que está no caso WM_PAINT dentro do caso WM_COMMAND, a imagem não é carregada. Provavelmente eu não posso fazer isso por algum motivo que desconheço porque sou iniciante.

  • Curtir 1
  • Solução
Postado
36 minutos atrás, Lucca Rodrigues disse:

Provavelmente eu não posso fazer isso por algum motivo que desconheço porque sou iniciante

🤔 A gente sempre desconhece mais do conhece...

 

BOOL InvalidateRect(
  HWND       hWnd,
  const RECT *lpRect,
  BOOL       bErase
);

Estou escrevendo sem pensar muito, mas talvez deva chamar essa rotina pra avisar o sistema de que algo mudou na janela, se isso não aconteceu por si

  • Curtir 1
  • Obrigado 1
Postado

@arfneto Obrigado.

InvalidateRect não redesenha imediatamente a janela, mas testei e funciona sim, chamei essa rotina dentro do caso WM_COMMAND e deu certo! Mas preferi usar RedrawWindow, mas eu poderia ter usado essa daí que você mencionou e ter chamado a função UpdateWindow logo depois.

Obrigado novamente pela ajuda.

 

  • Curtir 2
Postado
4 horas atrás, arfneto disse:

chamar essa rotina pra avisar o sistema de que algo mudou na janela

 

3 horas atrás, Lucca Rodrigues disse:

InvalidateRect não redesenha imediatamente a janela

 

Pois é. Foi o que eu disse. Windows funciona através e somente através do loop de mensagens. Essa rotina avisa o sistema de que um determinado retângulo de uma determinada janela foi invalidado e o sistema oportunamente vai ver se esse pedaço está visível e atualizar a tela. 

 

3 horas atrás, Lucca Rodrigues disse:

Mas preferi usar RedrawWindow, mas eu poderia ter usado essa daí que você mencionou e ter chamado a função UpdateWindow logo depois

 

O normal é usar InvalidadeRect() e deixar por conta do sistema, porque ele escolhe a hora e a necessidade e gera WM_PAINT para a janela correspondente, se ela estiver visível. Mais uma vez estou escrevendo de memória, mas acho que por exemplo RedrawWindow() recria a imagem da janela mesmo que ela não esteja visível, e sempre da janela toda. E InvalidadeRect() vai levar a mostrar só o que mudou e só se está numa região visível da tela

 

Um pouco off-topic, mas recomendo usar um framework para tratar essas coisas. É mais flexível. Algo como WxWidgets ou SDL ou GTK+ ou Qt. 

  • Curtir 1
  • Obrigado 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...