#include "main.h" #include "./backBuffer.h" BOOL BackBuffer_Initialize(BackBuffer *self, HWND hwnd) { if (NULL == self) return FALSE; ZeroMemory(self, sizeof(BackBuffer)); self->hwnd = hwnd; return TRUE; } void BackBuffer_Uninitialize(BackBuffer *self) { BackBuffer_Reset(self); } void BackBuffer_Reset(BackBuffer *self) { if (NULL == self) return; if (NULL != self->hdc) { if (NULL != self->previous) SelectBitmap(self->hdc, self->previous); DeleteDC(self->hdc); } if (NULL != self->bitmap) { DeleteObject(self->bitmap); } ZeroMemory(self, sizeof(BackBuffer)); } BOOL BackBuffer_EnsureSize(BackBuffer *self, long width, long height) { return BackBuffer_EnsureSizeEx(self, width, height, width, height); } BOOL BackBuffer_EnsureSizeEx(BackBuffer *self, long width, long height, long allocWidth, long allocHeight) { BOOL result; HDC windowDC; HBITMAP bitmap; long bitmapWidth, bitmapHeight; if (NULL == self) return FALSE; if (width < 0) width = 0; if (height < 0) height = 0; if (NULL != self->bitmap) { BITMAP bitmapInfo; if (sizeof(bitmapInfo) == GetObject(self->bitmap, sizeof(bitmapInfo), &bitmapInfo)) { if (bitmapInfo.bmWidth >= width && bitmapInfo.bmHeight >= height) return TRUE; bitmapWidth = bitmapInfo.bmWidth; bitmapHeight = bitmapInfo.bmHeight; } else { bitmapWidth = 0; bitmapHeight = 0; } } else { bitmapWidth = 0; bitmapHeight = 0; } result = FALSE; bitmap = NULL; windowDC = GetDCEx(self->hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS); if(NULL != windowDC) { if (allocWidth < width) allocWidth = width; if (allocWidth < bitmapWidth) allocWidth = bitmapWidth; if (allocHeight < height) allocHeight = height; if (allocHeight < bitmapHeight) allocHeight = bitmapHeight; bitmap = CreateCompatibleBitmap(windowDC, allocWidth, allocHeight); ReleaseDC(self->hwnd, windowDC); } if (NULL != bitmap) { if (NULL != self->hdc) SelectBitmap(self->hdc, bitmap); if (NULL != self->bitmap) DeleteObject(self->bitmap); self->bitmap = bitmap; result = TRUE; } return result; } HDC BackBuffer_GetDC(BackBuffer *self) { if (NULL == self) return FALSE; if (NULL == self->hdc) { HDC windowDC; windowDC = GetDCEx(self->hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS); if (NULL != windowDC) { self->hdc = CreateCompatibleDC(windowDC); ReleaseDC(self->hwnd, windowDC); if (NULL != self->hdc) { if (NULL != self->bitmap) self->previous = SelectBitmap(self->hdc, self->bitmap); else self->previous = GetCurrentBitmap(self->hdc); } } } return self->hdc; } BOOL BackBuffer_Copy(BackBuffer *self, HDC hdc, long x, long y, long width, long height) { HDC sourceDC; if (NULL == self || NULL == self->bitmap) return FALSE; sourceDC = BackBuffer_GetDC(self); if (NULL == sourceDC) return FALSE; return BitBlt(hdc, x, y, width, height, sourceDC, 0, 0, SRCCOPY); } BOOL BackBuffer_DrawTextEx(BackBuffer *self, HDC hdc, const wchar_t *string, int length, RECT *rect, unsigned int format, HFONT font, COLORREF backColor, COLORREF textColor, int backMode) { BOOL result = FALSE; RECT bufferRect; if (NULL == hdc || NULL == rect) return FALSE; SetRect(&bufferRect, 0, 0, RECTWIDTH(*rect), RECTHEIGHT(*rect)); if (NULL != self && FALSE != BackBuffer_EnsureSize(self, bufferRect.right, bufferRect.bottom)) { HDC bufferDC = BackBuffer_GetDC(self); if (NULL != bufferDC) { HFONT prevFont; prevFont = SelectFont(bufferDC, font); SetTextColor(bufferDC, textColor); SetBkColor(bufferDC, backColor); SetBkMode(bufferDC, backMode); if (OPAQUE == backMode) ExtTextOut(bufferDC, 0, 0, ETO_OPAQUE, &bufferRect, NULL, 0, NULL); if (FALSE != DrawText(bufferDC, string, length, &bufferRect, format)) { result = BackBuffer_Copy(self, hdc, rect->left, rect->top, bufferRect.right, bufferRect.bottom); } SelectFont(bufferDC, prevFont); } } if (FALSE == result) { HFONT prevFont; COLORREF prevBackColor, prevTextColor; int prevBkMode; prevFont = SelectFont(hdc, font); prevTextColor = SetTextColor(hdc, textColor); prevBackColor = SetBkColor(hdc, backColor); prevBkMode= SetBkMode(hdc, backMode); result = DrawText(hdc, string, length, rect, format); SelectFont(hdc, prevFont); SetTextColor(hdc, prevTextColor); SetBkColor(hdc, prevBackColor); SetBkMode(hdc, prevBkMode); } return result; } BOOL BackBuffer_DrawText(BackBuffer *self, HDC hdc, const wchar_t *string, int length, RECT *rect, unsigned int format) { BOOL result = FALSE; RECT bufferRect; if (NULL == hdc || NULL == rect) return FALSE; SetRect(&bufferRect, 0, 0, RECTWIDTH(*rect), RECTHEIGHT(*rect)); if (NULL != self && FALSE != BackBuffer_EnsureSize(self, bufferRect.right, bufferRect.bottom)) { HDC bufferDC = BackBuffer_GetDC(self); if (NULL != bufferDC) { HFONT prevFont; int backMode; prevFont = SelectFont(bufferDC, GetCurrentFont(hdc)); SetTextColor(bufferDC, GetTextColor(hdc)); SetBkColor(bufferDC, GetBkColor(hdc)); backMode = GetBkMode(hdc); SetBkMode(bufferDC, backMode); if (OPAQUE == backMode) ExtTextOut(bufferDC, 0, 0, ETO_OPAQUE, &bufferRect, NULL, 0, NULL); if (FALSE != DrawText(bufferDC, string, length, &bufferRect, format)) { result = BackBuffer_Copy(self, hdc, rect->left, rect->top, bufferRect.right, bufferRect.bottom); } SelectFont(bufferDC, prevFont); } } if (FALSE == result) result = DrawText(hdc, string, length, rect, format); return result; }