|   | 
			  void sheet_refresh(HDC hdc, RECT rect){
 HBITMAP hbmpMem = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top);
 HDC hdcMem = CreateCompatibleDC(hdc);
 SelectObject(hdcMem, hbmpMem);
 
 HDC hdcBmp = CreateCompatibleDC(hdc);
 RECT rcDraw, rcSheet;
 int z;
 for (z = 0; z <= shtctl->top; z++)
 {
 rcSheet.left = shtctl->sheets[z]->x;
 rcSheet.top = shtctl->sheets[z]->y;
 rcSheet.right = rcSheet.left + shtctl->sheets[z]->width;
 rcSheet.bottom = rcSheet.top + shtctl->sheets[z]->height;
 if (!IntersectRect(&rcDraw, &rcSheet, &rect))
 continue;
 
 RECT rcDrawMem = rcDraw;
 OffsetRect(&rcDrawMem, -rect.left, -rect.top);
 SelectObject(hdcBmp, shtctl->sheets[z]->hbmp);
 if (shtctl->sheets[z]->invisible_color == -1)
 BitBlt(hdcMem, rcDrawMem.left, rcDrawMem.top, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, hdcBmp, rcDraw.left - rcSheet.left, rcDraw.top - rcSheet.top, SRCCOPY);
 else
 TransparentBlt(hdcMem, rcDrawMem.left, rcDrawMem.top, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, hdcBmp, rcDraw.left - rcSheet.left, rcDraw.top - rcSheet.top, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, shtctl->sheets[z]->invisible_color);
 }
 BitBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdcMem, 0, 0, SRCCOPY);
 DeleteDC(hdcBmp);
 DeleteDC(hdcMem);
 DeleteObject(hbmpMem);
 }
 | 
                
          |   | 
			  #include <tchar.h>#include <Windows.h>
 #include "graphic.h"
 #include "memman.h"
 #include "sheet.h"
 extern HINSTANCE hInst;
 extern HWND hWnd;
 extern SHEET *sht_back, *sht_cursor;
 SHTCTL *shtctl;
 SHEET *create_window(LPCTSTR title, int x, int y, int width, int height, HDC *hdc, COLORREF invisible_color)
 {
 SHEET *win = sheet_alloc();
 win->title = title;
 sheet_create_bitmap(win, width, height, -1);
 HDC hdcWin = sheet_begin_paint(win);
 draw_window(hdcWin, width, height, title);
 if (hdc == NULL)
 sheet_end_paint(win, hdcWin);
 else
 *hdc = hdcWin;
 sheet_move(win, x, y);
 sheet_setz(win, shtctl->top);
 return win;
 }
 void sheet_active(SHEET *sht)
 {
 if (shtctl->active == sht)
 return;
 HDC hdc;
 if (sht != sht_back && sht != sht_cursor)
 {
 hdc = sheet_begin_paint(sht);
 draw_window_titlebar(hdc, sht->width, sht->title, true);
 sheet_end_paint(sht, hdc);
 }
 if (shtctl->active != NULL && shtctl->active != sht_back && shtctl->active != sht_cursor)
 {
 // not screen, not mouse
 hdc = sheet_begin_paint(shtctl->active);
 draw_window_titlebar(hdc, shtctl->active->width, shtctl->active->title, false);
 sheet_end_paint(shtctl->active, hdc);
 }
 caret_hide();
 shtctl->active = sht;
 caret_show();
 if (sht != sht_back && sht != sht_cursor)
 {
 if (sht->z != shtctl->top - 1)
 sheet_top(sht);
 }
 }
 SHEET *sheet_alloc(LPVOID param)
 {
 SHEET *sht;
 int i;
 for (i = 0; i < MAX_SHEETS; i++)
 {
 if (shtctl->sheets0[i].flags == 0)
 {
 sht = &shtctl->sheets0[i];
 sht->flags = SHEET_USE;
 sht->z = -1; // hide
 sht->param = param;
 sheet_remove_caret(sht);
 return sht;
 }
 }
 return NULL;
 }
 /* 返回一个绘制图层的HDC */
 HDC sheet_begin_paint(SHEET *sht)
 {
 HDC hdc = GetDC(hWnd);
 HDC hdcMem = CreateCompatibleDC(hdc);
 ReleaseDC(hWnd, hdc);
 DeleteDC(hdc);
 SelectObject(hdcMem, sht->hbmp);
 SelectObject(hdcMem, GetStockObject(NULL_PEN));
 return hdcMem;
 }
 void sheet_create_bitmap(SHEET *sht, int width, int height, COLORREF invisible_color)
 {
 HDC hdc = GetDC(hWnd);
 sheet_create_bitmap(sht, hdc, width, height, invisible_color);
 ReleaseDC(hWnd, hdc);
 DeleteDC(hdc);
 }
 void sheet_create_bitmap(SHEET *sht, HDC hdc, int width, int height, COLORREF invisible_color)
 {
 sht->hbmp = CreateCompatibleBitmap(hdc, width, height);
 sheet_setinfo(sht, width, height, invisible_color);
 }
 /* 若要指定hdc, 请改用draw_text函数并手动完成刷新(或者刷新整个图层也行) */
 SIZE sheet_draw_text(SHEET *sht, int x, int y, COLORREF text_color, COLORREF bk_color, LPCTSTR str, int refresh_width)
 {
 HDC hdc = sheet_begin_paint(sht);
 int len = _tcslen(str);
 SIZE size = draw_text(hdc, x, y, text_color, bk_color, str, refresh_width);
 sheet_end_paint(sht, hdc, x, y, (refresh_width == 0) ? (x + size.cx) : (x + refresh_width), y + size.cy);
 return size;
 }
 /* 结束绘制并刷新整个图层 */
 void sheet_end_paint(SHEET *sht, HDC hdcMem)
 {
 DeleteDC(hdcMem);
 sheet_refresh(sht);
 }
 /* 结束绘制并刷新图层中的指定区域 */
 void sheet_end_paint(SHEET *sht, HDC hdcMem, int x0, int y0, int x1, int y1)
 {
 sheet_end_paint(sht, hdcMem, make_rect(x0, y0, x1, y1));
 }
 void sheet_end_paint(SHEET *sht, HDC hdcMem, RECT rect)
 {
 DeleteDC(hdcMem);
 sheet_refresh(sht, rect);
 }
 /* 删除图层 */
 void sheet_free(SHEET *sht)
 {
 if (shtctl->active == sht)
 shtctl->active = NULL;
 if (sht->z >= 0)
 sheet_setz(sht, -1);
 DeleteObject(sht->hbmp);
 sht->hbmp = NULL;
 sht->flags = 0;
 }
 void sheet_load_bitmap(SHEET *sht, int iBmp, COLORREF invisible_color)
 {
 BITMAP bmp;
 sht->hbmp = LoadBitmap(hInst, MAKEINTRESOURCE(iBmp));
 GetObject(sht->hbmp, sizeof(bmp), &bmp);
 sheet_setinfo(sht, bmp.bmWidth, bmp.bmHeight, invisible_color);
 }
 void sheet_move(SHEET *sht, int x, int y)
 {
 int old_x = sht->x;
 int old_y = sht->y;
 sht->x = x;
 sht->y = y;
 if (sht->z >= 0)
 {
 sheet_refresh(old_x, old_y, old_x + sht->width, old_y + sht->height);
 sheet_refresh(x, y, x + sht->width, y + sht->height);
 }
 }
 /* 刷新整个画面 */
 void sheet_refresh(void)
 {
 RECT rect;
 GetClientRect(hWnd, &rect);
 InvalidateRect(hWnd, &rect, FALSE);
 }
 /* 在HDC上绘制指定区域的画面 */
 void sheet_refresh(HDC hdc, RECT rect)
 {
 HBITMAP hbmpMem = CreateCompatibleBitmap(hdc, rect.right - rect.left, rect.bottom - rect.top);
 HDC hdcMem = CreateCompatibleDC(hdc);
 SelectObject(hdcMem, hbmpMem);
 HDC hdcBmp = CreateCompatibleDC(hdc);
 RECT rcDraw, rcSheet;
 int z;
 for (z = 0; z <= shtctl->top; z++)
 {
 rcSheet.left = shtctl->sheets[z]->x;
 rcSheet.top = shtctl->sheets[z]->y;
 rcSheet.right = rcSheet.left + shtctl->sheets[z]->width;
 rcSheet.bottom = rcSheet.top + shtctl->sheets[z]->height;
 if (!IntersectRect(&rcDraw, &rcSheet, &rect))
 continue;
 
 RECT rcDrawMem = rcDraw;
 OffsetRect(&rcDrawMem, -rect.left, -rect.top);
 SelectObject(hdcBmp, shtctl->sheets[z]->hbmp);
 if (shtctl->sheets[z]->invisible_color == -1)
 BitBlt(hdcMem, rcDrawMem.left, rcDrawMem.top, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, hdcBmp, rcDraw.left - rcSheet.left, rcDraw.top - rcSheet.top, SRCCOPY);
 else
 TransparentBlt(hdcMem, rcDrawMem.left, rcDrawMem.top, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, hdcBmp, rcDraw.left - rcSheet.left, rcDraw.top - rcSheet.top, rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top, shtctl->sheets[z]->invisible_color);
 }
 BitBlt(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, hdcMem, 0, 0, SRCCOPY);
 DeleteDC(hdcBmp);
 DeleteDC(hdcMem);
 DeleteObject(hbmpMem);
 }
 void sheet_refresh(int x0, int y0, int x1, int y1)
 {
 InvalidateRect(hWnd, &make_rect(x0, y0, x1, y1), FALSE);
 }
 void sheet_refresh(RECT rect)
 {
 InvalidateRect(hWnd, &rect, FALSE);
 }
 void sheet_refresh(SHEET *sht)
 {
 RECT rect;
 rect.left = sht->x;
 rect.top = sht->y;
 rect.right = sht->x + sht->width;
 rect.bottom = sht->y + sht->height;
 sheet_refresh(rect);
 }
 void sheet_refresh(SHEET *sht, RECT rect)
 {
 OffsetRect(&rect, sht->x, sht->y);
 sheet_refresh(rect);
 }
 void sheet_set_caret(SHEET *sht, int x, int y, COLORREF color, COLORREF bkColor)
 {
 sheet_set_caret(sht, x, y, CARET_DEF_WIDTH, CARET_DEF_HEIGHT, color, bkColor);
 }
 void sheet_set_caret(SHEET *sht, int x, int y, int width, int height, COLORREF color, COLORREF bkColor)
 {
 sht->caret.back_color = bkColor;
 sht->caret.color = color;
 sht->caret.rect.left = x;
 sht->caret.rect.top = y;
 sht->caret.rect.right = x + width;
 sht->caret.rect.bottom = y + height;
 }
 void sheet_setinfo(SHEET *sht, int width, int height, COLORREF invisible_color)
 {
 sht->width = width;
 sht->height = height;
 sht->invisible_color = invisible_color;
 }
 void sheet_setz(SHEET *sht, int z_index)
 {
 int z;
 int old = sht->z;
 if (z_index > shtctl->top + 1)
 z_index = shtctl->top + 1;
 if (z_index < -1)
 z_index = -1;
 sht->z = z_index;
 if (old > z_index)
 {
 if (z_index >= 0)
 {
 for (z = old; z > z_index; z--)
 {
 shtctl->sheets[z] = shtctl->sheets[z - 1];
 shtctl->sheets[z]->z = z;
 }
 shtctl->sheets[z_index] = sht;
 }
 else
 {
 // hide
 if (shtctl->top > old)
 {
 for (z = old; z < shtctl->top; z++)
 {
 shtctl->sheets[z] = shtctl->sheets[z + 1];
 shtctl->sheets[z]->z = z;
 }
 }
 shtctl->top--;
 }
 sheet_refresh(sht->x, sht->y, sht->x + sht->width, sht->y + sht->height);
 }
 else if (old < z_index)
 {
 if (old >= 0)
 {
 for (z = old; z < z_index; z++)
 {
 shtctl->sheets[z] = shtctl->sheets[z + 1];
 shtctl->sheets[z]->z = z;
 }
 shtctl->sheets[z_index] = sht;
 }
 else
 {
 // display
 for (z = shtctl->top; z >= z_index; z--)
 {
 shtctl->sheets[z + 1] = shtctl->sheets[z];
 shtctl->sheets[z + 1]->z = z + 1;
 }
 shtctl->sheets[z_index] = sht;
 shtctl->top++;
 }
 sheet_refresh(sht->x, sht->y, sht->x + sht->width, sht->y + sht->height);
 }
 }
 void shtctl_init(void)
 {
 RECT rect;
 GetClientRect(hWnd, &rect);
 shtctl_init(rect.right - rect.left, rect.bottom - rect.top);
 }
 void shtctl_init(int width, int height)
 {
 int i;
 shtctl = (SHTCTL *)memman_alloc_4k(sizeof(SHTCTL));
 shtctl->width = width;
 shtctl->height = height;
 shtctl->top = -1;
 shtctl->active = shtctl->closing = NULL;
 shtctl->move_info.sht = NULL;
 for (i = 0; i < MAX_SHEETS; i++)
 shtctl->sheets0[i].flags = 0;
 }
 
 |