/* File "OVERLAY.C" - Code to overlay a RichText control over a background    */
/* Code by Matt Slot <fprefect@ambrosiasw.com> and placed into public domain  */
  #include <COMMCTRL.H>
#include <RICHEDIT.H>
#include <WINDOWSX.H>
#include <WINDOWS.H>
  /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* Preprocessor Definitions */
  #define OVERLAY_CLASS   "OVERLAY"
#define PROGRAM_NAME    "RichEdit Overlay"
#define STRING          "abcde fghij klmno pqrst uvwxyz 01234 56789 "
  /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* Function Prototypes */
  typedef BOOL WINAPI (*TransparentBltProc)(IN HDC,IN int,IN int,IN int,
                            IN int,IN HDC,IN int,IN int,IN int,IN int,IN UINT);
  BOOL RichEditOverlayHWND(HWND hwnd, HDC hdc, HWND hwndRich);
BOOL RichEditOverlayHDC(HDC hdc, DWORD x, DWORD y, HWND hwndRich);
  /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* Overlay the contents of a HWND with a RichEdit control (its child window)  */ 
  BOOL RichEditOverlayHWND(HWND hwnd, HDC hdc, HWND hwndRich) {
    POINT           point = { 0, 0 };
      /* Just get the window location from our parent window */
    if (IsChild(hwnd, hwndRich)) MapWindowPoints(hwndRich, hwnd, &point, 1);
      return(RichEditOverlayHDC(hdc, point.x, point.y, hwndRich));
    }
    
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* Overlay the contents of the HDC at the given point with a RichEdit control */ 
  BOOL RichEditOverlayHDC(HDC hdc, DWORD x, DWORD y, HWND hwndRich) {
    static TransparentBltProc gTransparentBltProc = NULL;
    static BOOL     gTransparentBltFirst = TRUE;
    BOOL            success = TRUE;
    HDC             hdcSave = NULL;
    HDC             hdcRich = NULL, hdcMask = NULL;
    HBITMAP         hbmRich = NULL, hbmSaveRich = NULL;
    HBITMAP         hbmMask = NULL, hbmSaveMask = NULL;
    COLORREF        bkColor;
    DWORD           bits, w, h;
    POINT           point;
    RECT            rect;
      /* On our first call, we try to dynamically load TransparentBlt() */
    if (gTransparentBltFirst) {
        HINSTANCE   hModule = LoadLibrary("MSIMG32.DLL");
        if (hModule) 
            gTransparentBltProc = GetProcAddress(hModule, "TransparentBlt");
        gTransparentBltFirst = FALSE; /* Don't bother trying again */
        }
      /* Establish our coordinates from the start. */
    GetClientRect(hwndRich, &rect);
    w = rect.right - rect.left;
    h = rect.bottom - rect.top;
    
    /* Get the relevant characteristics of the source window */
    hdcSave = GetDC(hwndRich);
    if (!hdcSave) { success = FALSE; goto CLEANUP; }
    bkColor = GetBkColor(hdcSave);
    bits = GetDeviceCaps(hdcSave, BITSPIXEL);
      /* Create offscreen drawing contexts and bitmap for the pixels */
    hdcRich = CreateCompatibleDC(hdcSave);
    if (!hdcRich) { success = FALSE; goto CLEANUP; }
    hbmRich = CreateBitmap(w, h, 1, bits, NULL);
    if (!hbmRich) { success = FALSE; goto CLEANUP; }
    hbmSaveRich = SelectBitmap(hdcRich, hbmRich);
      /* Create offscreen drawing contexts and bitmap for the mask */
    if (!gTransparentBltProc) {
        hdcMask = CreateCompatibleDC(hdcSave);
        if (!hdcMask) { success = FALSE; goto CLEANUP; }
        hbmMask = CreateBitmap(w, h, 1, 1, NULL);
        if (!hbmMask) { success = FALSE; goto CLEANUP; }
        hbmSaveMask = SelectBitmap(hdcMask, hbmMask);
        }
      /* Draw the control into our offscreen drawing context */
    SendMessage(hwndRich, WM_PRINT, (WPARAM) hdcRich, 
            PRF_CLIENT | PRF_ERASEBKGND);
      if (gTransparentBltProc)
        /* We'll gladly use it if it's available */
        success = (*gTransparentBltProc)(hdc,x,y,w,h,hdcRich,0,0,w,h,bkColor);
      else {
        /* Otherwise use a mask and draw it manually */
        BitBlt(hdcMask,0,0,w,h,hdcRich,0,0,SRCCOPY);
        BitBlt(hdc,x,y,w,h,hdcMask,0,0,SRCAND);
        BitBlt(hdcRich,0,0,w,h,hdcMask,0,0,0x00220326); /* SRCNOTAND */
        success = BitBlt(hdc,x,y,w,h,hdcRich,0,0,SRCPAINT);
        }
  CLEANUP:
      /* Release all of our objects in order */
    if (hbmSaveMask) SelectBitmap(hdcMask, hbmSaveMask);
    if (hbmMask) DeleteObject(hbmMask);
    if (hbmSaveRich) SelectBitmap(hdcRich, hbmSaveRich);
    if (hbmRich) DeleteObject(hbmRich);
    if (hdcSave) ReleaseDC(hwndRich, hdcSave);
      return(success);
    }
  /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* Private utility routines */
  #define kFirstChildWindowID     10000
  static BOOL CALLBACK CalcChildWindowProc(HWND hwnd, LPARAM param) {
    HMENU *     child = (HMENU *) param;
      if (*child == (HMENU) GetDlgCtrlID(hwnd)) *child = (HMENU) NULL;
    
    return((*child) ? TRUE : FALSE);
    }
 
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  static HMENU CalcChildWindowID(HWND hwnd) {
    HMENU       child;
    UINT        i;
      for(i=kFirstChildWindowID, child=(HMENU) NULL; !child; child = (HMENU) ++i)
        EnumChildWindows(hwnd, CalcChildWindowProc, (LPARAM) &child);
    
    return(child);
    }
 
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  static LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, 
        LPARAM lParam) {
    LRESULT         result = 0;
    HWND            hwndRich;
    HDC             hdc;
    PAINTSTRUCT     ps;
    
    switch(msg) {
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
              /* Grab the RichEdit handle from the parent window */
            hwndRich = (HWND) GetWindowLong(hwnd, GWL_USERDATA);
            RichEditOverlayHWND(hwnd, hdc, hwndRich);
              EndPaint(hwnd, &ps);
            result = 1;
            break;
          case WM_DESTROY:
            PostQuitMessage(0);
            break;
    
        default:
            result = DefWindowProc(hwnd, msg, wParam, lParam);
        }
      return(result);
    }
  /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
/* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
  int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszCmdLine, 
        int nCmdShow) {
    HWND            hwnd = (HWND) NULL;
    HWND            hwndRich = (HWND) NULL;
    MSG             lpMsg;
    WNDCLASS        wc;
    RECT            rect;
    HDC             hdc;
    UINT            i, j;
    CHARFORMAT      cf;
      /* Create our class and use an interesting background brush */
    if (!hPrev) {
        wc.lpszClassName    = OVERLAY_CLASS;
        wc.hInstance        = hInst;
        wc.lpfnWndProc      = MyWndProc;
        wc.hCursor          = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
        wc.hIcon            = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);
        wc.lpszMenuName     = (char *) NULL;
        wc.hbrBackground    = CreateHatchBrush(HS_BDIAGONAL, RGB(255,0,0));
        wc.style            = 0;
        wc.cbClsExtra       = 0;
        wc.cbWndExtra       = 0;
          if (!RegisterClass(&wc)) return FALSE;
        }
      /* Create the window */
    hwnd = CreateWindow(OVERLAY_CLASS, PROGRAM_NAME, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
            (HWND) NULL, (HMENU) NULL, (HINSTANCE) hInst, (LPSTR) NULL);
      /* Create the RichEdit control -- notice, we never make it visible! */
    InitCommonControls();
    LoadLibrary("RICHED32.DLL");
    GetClientRect(hwnd, &rect);
    hwndRich = CreateWindowEx(0, "RICHEDIT", "", WS_CHILD | ES_LEFT | 
            ES_SAVESEL | ES_MULTILINE | ES_AUTOVSCROLL, rect.left + 50,
            rect.top + 50, rect.right - rect.left - 100, rect.bottom - 
            rect.top - 100, hwnd, CalcChildWindowID(hwnd), (HINSTANCE)
            GetWindowLong(hwnd, GWL_HINSTANCE), NULL);
    Edit_Enable(hwndRich, FALSE);
    hdc = GetDC(hwndRich);
    
    /* Fill the image with some interesting text, 1 run at a time */
    ZeroMemory(&cf, sizeof(CHARFORMAT));
    cf.cbSize = sizeof(CHARFORMAT);
    cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_ITALIC | 
                        CFM_SIZE | CFM_UNDERLINE;
    cf.dwEffects = 0;
    cf.yHeight = 120 / GetDeviceCaps(hdc, LOGPIXELSY);
    cf.yOffset = 0;
    cf.crTextColor = RGB(0,0,0);
    cf.bCharSet = ANSI_CHARSET;
    cf.bPitchAndFamily = DEFAULT_PITCH;
    strcpy(cf.szFaceName, "System");
    for(i=0, j=sizeof(STRING)-sizeof(""); i<27; i++) {
        Edit_SetSel(hwndRich, j*i, j*i);
        Edit_ReplaceSel(hwndRich, STRING);
        Edit_SetSel(hwndRich, j*i, j*(i+1));
          /* Format the text */
        cf.crTextColor = RGB((i%3)*0x44,((i/3)%3)*0x44,((i/9)%3)*0x44);
        SendMessage(hwndRich, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf);
        }
    Edit_SetSel(hwndRich, 0, 0);
    ReleaseDC(hwndRich, hdc);
      /* Store the handle to the child window so we can access it */
    SetWindowLong(hwnd, GWL_USERDATA, (LONG) hwndRich);
      /* Sit and spin */
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    while(GetMessage(&lpMsg, (HWND) NULL, 0, 0)) {
        TranslateMessage(&lpMsg);
        DispatchMessage(&lpMsg);
        }
        
    DestroyWindow(hwnd);
    return(lpMsg.wParam);
    }
 
 
     |