bitmap regions, combine multiple or seperate for effect?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • rollerbladegirl
    New Member
    • Jan 2020
    • 69

    bitmap regions, combine multiple or seperate for effect?

    For the following: This is my main question:
    *Most of all* should I be doing this making these combined (make multiple regions at the same time) or in separate threads (if I am to have many of them)?



    I asked about some bitmap regions in a previous post.

    https://bytes.com/topic/c/answers/973517-c-11-seperately-controlled-regions

    I do not know if I should have replaced the previous one or added to it.

    In a later discussion I was reminded of multi-threading. I am now wondering if in my attempts to display two independent bitmap regions maybe together was incorrect. Maybe I should have considered multi-threading them separately.

    (1)
    Make a bitmap region, save it somehow, then after that is completed make a second bitmap and save it. Then copy those to the screen (dc?).

    or

    (2)
    This is stretching my capacity as I started in C++ ~6 months ago: Create two threads: Create a thread and make one bitmap custom region in a thread and save it to a global (dc?); Create a second thread and make a second bitmap custom region in that thread and save it to a second global (dc?). Then, when both threads report completed, combine the bitmap custom regions into one single region and put it to the screen (dc?).

    That was intense to just write in.

    Thoughts?

    I kind of have this written. Not fully, but here it is.

    NOTE: Problem: It kind of works, but it first shows a square grey window which I do not want but which goes away (I do not want it at all), then it shows a red X then it shows a blue mess, then the red X turns grey.

    The now-grey X when I leftmouse click on it becomes forefront and can be moved. The blue mess when I left mouse click on it becomes forefront and can be moved.

    Please help me to make the red X stay red.

    Please help me to make the initial grey square not show up.

    Please help me to make certain that I am cleaning up any memory correctly.

    But *most of all* should I be doing this making these combined or in separate threads (if I am to have many of them)?

    Thanks.

    (I am including it all since I have read multiple times where readers have asked for more information from the poster.)


    main.cpp
    Code:
    #ifndef IDC_STATIC
        #define IDC_STATIC (-1)
    #endif
    
    #ifndef _UNICODE
        #define _UNICODE
    #endif // _UNICODE
    
    #ifndef UNICODE
        #define UNICODE
    #endif // UNICODE
    
    //#include "JM_Defines_and_Includes.h"
    
    //----------
    
    #include "windows.h"
    #include "resource.h"
    
    #define MAX_LOADSTRING 100
    
    // Global Variables:
    
        HINSTANCE InstanceHandleOfMainWindow;	// Instance handle of the main window
    
        TCHAR szTitle[MAX_LOADSTRING];			// The title bar text
    
        HWND Handle_MainWindow = NULL;          // Handle to main application window
    
        HRGN hRgn = NULL;                       // Handle to region
    
        HDC hdcDest;                            // Dest DC
    
        HDC hdcMem;                             // Memory DC
    
        BITMAP bmpInfo;                         // Buffer to hold bitmap data
    
        BOOL mouseState = 0;                    // Global variable for moving region using mouse
    
        POINT CursPt = {0};                     // Global variable for moving region using mouse
    
        wchar_t WindowClass_for_WinMain[MAX_LOADSTRING] = L"(myWindowClass)";
    
    //    const wchar_t WindowClass_for_WinMain[MAX_LOADSTRING] = L"(myWindowClass)";
    
    // Forward declarations of functions included later in this code module:
    
        ATOM				RegisterTheMainWindowClass(HINSTANCE hInstance2);
    
        BOOL				DidTheMainWindowClassRegisterCorrectly(HINSTANCE, int);
    
        LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
    
        LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
    
    // Empty function to be used later to create region based on the bitmap
    
        void createRegion_A(HWND);
        void createRegion_B(HWND);
    
    // Empty Function to be used later to paint a region window
    
        void paintRegion();
    
    // Empty Dialog callback procedure declaration to be used later
    
        INT_PTR CALLBACK DialogProc( HWND Handle_DialogBox1, UINT uMsg, WPARAM wParam, LPARAM lParam );
    
    
    int APIENTRY WinMain(HINSTANCE hInstance1, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    
        {
            MSG msg;
    
            RegisterTheMainWindowClass(hInstance1);
    
            if (!DidTheMainWindowClassRegisterCorrectly (hInstance1, nCmdShow))
                {
                    return FALSE;
                }
    
            // Message loop
            while (GetMessage(&msg, nullptr, 0, 0))
                {
                    DispatchMessage(&msg);
                }
    
            return msg.wParam;
        }
    
    
    ATOM RegisterTheMainWindowClass(HINSTANCE hInstance3)
    
        // An ATOM is created when the class is registered.
        // This might be a secure reference to window class in that it is special to the kernel.
        // Maybe (typedef unsigned short ATOM;)
        // ATOM is a 16-bit Windows handle-like primitive.
            // It is value is completely opaque to user-mode.
            // It is not a pointer or an index.
        // They are indexes into a handle table in kernel mode.
            // They are deliberately opaque because leaking kernel mode
            // pointers to user-mode is a security violation (whatever that means).
        {
            WNDCLASSEX wcex;
    
            wcex.cbSize = sizeof(WNDCLASSEX);
    
            wcex.style			= CS_HREDRAW | CS_VREDRAW;
                // CS_HREDRAW is for HORIZONTAL;
                    // It redraws the entire window if a movement or size adjustment changes the width of the client area.
                // CS_VREDRAW is for VERTICAL;
                    // It redraws the entire window if a movement or size adjustment changes the height of the client area.
            wcex.lpfnWndProc	= (WNDPROC)WndProc;
            wcex.cbClsExtra		= 0;
            wcex.cbWndExtra		= 0;
            wcex.hInstance		= hInstance3;
            wcex.hIcon			= nullptr;
            wcex.hCursor		= LoadCursor(nullptr, IDC_ARROW);
            wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
            wcex.lpszMenuName	= nullptr;
            wcex.lpszClassName	= WindowClass_for_WinMain;
            wcex.hIconSm		= nullptr;
    
            // Return type is ATOM.
            return RegisterClassEx(&wcex);
        }
    
    BOOL DidTheMainWindowClassRegisterCorrectly(HINSTANCE hInstance4, int nCmdShow)
        {
            InstanceHandleOfMainWindow = hInstance4; // Store the instance handle in a previously created global variable
    
            Handle_MainWindow = CreateWindow(
                WindowClass_for_WinMain,
                szTitle,
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                0,
                100,
                150,
                NULL,
                NULL,
                hInstance4,
                NULL);
    
            if (!Handle_MainWindow)
                {
                    return FALSE;
                }
    
            // Create a dialog box
            HWND Handle_DialogBox2 = CreateDialog(hInstance4, MAKEINTRESOURCE(IDD_DIALOG1), Handle_MainWindow, (DLGPROC)DialogProc);
            // Create a region
            createRegion_A(Handle_DialogBox2);
    
            HWND Handle_DialogBox3 = CreateDialog(hInstance4, MAKEINTRESOURCE(IDD_DIALOG1), Handle_MainWindow, (DLGPROC)DialogProc);
            // Create a region
            createRegion_B(Handle_DialogBox3);
    
            // Don't have to show or update the window ?
            // ShowWindow(hWnd, nCmdShow);
            // UpdateWindow(hWnd);
    
            return TRUE;
        }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
        {
            switch (message)
            {
    
                case WM_DESTROY:
                    {
                        DeleteObject(hRgn);
    
                        DeleteDC(hdcMem);       //Delete the memory DC
    
                        DeleteDC(hdcDest);      //delete the dest DC
    
                        PostQuitMessage(0);
                    }
                    return TRUE;
                    break;
    
                default:
                    {
                    }
                    return DefWindowProc(hWnd, message, wParam, lParam);
           }
           return 0;
        }
    
    
    INT_PTR CALLBACK DialogProc(            // Dialog callback procedure
                                            // INT_PTR is a signed integer memsize-type
                                            // that can store a pointer regardless of the platform capacity.
                HWND Handle_DialogBox01,    // Temporary (internal to this procedure) Handle to a dialog box
                UINT uMsg,                  // Message
                WPARAM wParam,              // First message parameter
                LPARAM lParam               // Second message parameter
            )
        {
    
            switch (uMsg)
            {
    
                case WM_PAINT:
                    {
                        paintRegion();
    
                        ValidateRect(Handle_DialogBox01,nullptr);   // ValidateRect(hwnd,FALSE);
                    }
                    return TRUE;
                    break;
    
                case WM_MOVE:
                    {
    //does not work here.
    //RedrawWindow(Handle_MainWindow, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
                        paintRegion();
                    }
                    return TRUE;
                    break;
    
    
                case WM_LBUTTONDOWN:
                    {
                        mouseState = 1;
    /*BOOL RedrawWindow(
        HWND       hWnd,
        const RECT *lprcUpdate,
        HRGN       hrgnUpdate,
        UINT       flags
        );
    */
    //Almost works here but back image is partially greyed out.
    RedrawWindow(Handle_MainWindow, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
    
                    }
                    return TRUE;
                    break;
    
                case WM_MOUSEMOVE:
                    {
                        if(mouseState)
                            {
                                GetCursorPos(&CursPt);
                                PostMessage(Handle_DialogBox01, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( CursPt.x, CursPt.y));
                                mouseState = 0;
                            }
    
                    }
                    return TRUE;
                    break;
    
                case WM_RBUTTONDOWN:
                    {
                        // Destroy the dialog box
                        EndDialog(Handle_DialogBox01,0);
    
                        // Send message to destroy the main application window and exit
                        SendMessage(Handle_MainWindow,WM_DESTROY,0,0);
                    }
                    return TRUE;
                    break;
    
                default :
                    {
                        break;
                    }
                    return TRUE;
                    break;
            }
            return FALSE;
        }
    
    void createRegion_A(HWND FunctionReferenceTo_DialogBox01)
        {
    
            HGDIOBJ hGdiObj;    // For Selecting a bitmap into the dc
            COLORREF crTransparent;
    
            int iX = 0;
            int iY = 0;
    
            int iRet01 = 0;     // Integer For region 1
    
            // Get the destination device context
            hdcDest = GetDC(FunctionReferenceTo_DialogBox01);
    
            // Create a memory DC
            hdcMem = CreateCompatibleDC(nullptr);
    
            HRGN FinalTransparentRegionFrom_Combined_Bitmaps;
            FinalTransparentRegionFrom_Combined_Bitmaps = CreateRectRgn(0,0,0,0);
    
            //----------------------------------------------------------------------
            // START   Load the image files
            //----------------------------------------------------------------------
    
                // a.bmp
                    wchar_t imageFile_A[] = L"a.bmp";
    
                    // Load the image
                    HANDLE Handle_Bitmap_A = (HBITMAP)LoadImage(GetModuleHandle(nullptr), imageFile_A, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    
                    if(!Handle_Bitmap_A)
                        {
                            // Handle error here
                            return;
                        }
    
    
            //----------------------------------------------------------------------
            // END     Load the image files
            //----------------------------------------------------------------------
    
    
    
    
            //----------------------------------------------------------------------
            // START   Create Region from imageFile_A
            //----------------------------------------------------------------------
    
                HRGN TemporaryRegion_for_Bitmap_A;
                HRGN FinalTransparentRegionFromBitmap_A;
    
    
                // Get information about the bitmap..
                GetObject(Handle_Bitmap_A, sizeof(bmpInfo), &bmpInfo);	// Get info about the bitmap
    
                // Select the bitmap into the dc
                hGdiObj = SelectObject(hdcMem, Handle_Bitmap_A);
    
                // Create a region from a bitmap with transparency colour of white
                // change the pixel values for a different transparency color
                // example - RGB(0,0,0) will mean a transparency color of black.. so the areas
                // of the bitmap not used to create the window will be black
                // COLORREF crTransparent = RGB(255, 255, 255);
                crTransparent = RGB(255, 255, 255);
    
    
                iX = 0;
                iY = 0;
                iRet01 = 0;
    
                FinalTransparentRegionFromBitmap_A = CreateRectRgn(0,0,0,0);
    
                for (iY = 0; iY < bmpInfo.bmHeight; iY++)
                    {
                        do
                        {
                            // Skip over transparent pixels at start of lines.
                            while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) == crTransparent)
                                {
                                    iX++;
                                }
    
                            // Remember this pixel
                            int iLeftX = iX;
    
                            // Now find first non transparent pixel
                            while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) != crTransparent)
                                {
                                    ++iX;
                                }
    
                            // Create a temp region on this info
                            TemporaryRegion_for_Bitmap_A = CreateRectRgn(iLeftX, iY, iX, iY+1);
    
                            // Combine into main region.
                            // From wingdi.h
                            // WINGDIAPI int WINAPI CombineRgn(HRGN,HRGN,HRGN,int);
                            // Combine Region1 & Region2 & store result in ResultRegion.
                            // CombineRgn(ResultRegion,Region1,Region2,RGN_AND);
                            iRet01 = CombineRgn(FinalTransparentRegionFromBitmap_A, FinalTransparentRegionFromBitmap_A, TemporaryRegion_for_Bitmap_A, RGN_OR);
                        }
    
                        while(iX < bmpInfo.bmWidth);
                        {
                            iX = 0;
                        }
                    }
    
                // Center it on current desktop
                iRet01 = SetWindowRgn(FunctionReferenceTo_DialogBox01, FinalTransparentRegionFromBitmap_A, TRUE);
    
                    if(!iRet01)
                        {
                            return;
                        }
    
                    iX = (GetSystemMetrics(SM_CXSCREEN)) / 3 - (bmpInfo.bmWidth / 3);
    
                    iY = (GetSystemMetrics(SM_CYSCREEN)) / 3 - (bmpInfo.bmHeight / 3);
    
                    iRet01 = SetWindowPos(FunctionReferenceTo_DialogBox01, HWND_TOPMOST, iX, iY, bmpInfo.bmWidth, bmpInfo.bmHeight, 0);
    
            //----------------------------------------------------------------------
            // END     Create Region from imageFile_A
            //----------------------------------------------------------------------
    
    
    
            // Copy the memory dc into the screen dc
            paintRegion();
    
            // Delete the bitmap
            DeleteObject(Handle_Bitmap_A);
    
    
        }   //void createRegion_A(HWND FunctionReferenceTo_DialogBox01)
    
    
    
    
    
    
    
    
    
    
    
    
    
     void createRegion_B(HWND FunctionReferenceTo_DialogBox01)
        {
    
            HGDIOBJ hGdiObj;    // For Selecting a bitmap into the dc
            COLORREF crTransparent;
    
            int iX = 0;
            int iY = 0;
    
            int iRet01 = 0;     // Integer For region 1
            int iRet02 = 0;     // Integer For region 2
            int iRet03 = 0;     // Integer For combined (already) transparent regions
    
    
            // Get the destination device context
            hdcDest = GetDC(FunctionReferenceTo_DialogBox01);
    
            // Create a memory DC
            hdcMem = CreateCompatibleDC(nullptr);
    
            HRGN FinalTransparentRegionFrom_Combined_Bitmaps;
            FinalTransparentRegionFrom_Combined_Bitmaps = CreateRectRgn(0,0,0,0);
    
            //----------------------------------------------------------------------
            // START   Load the image files
            //----------------------------------------------------------------------
    
    
                // b.bmp
                    wchar_t imageFile_B[] = L"b.bmp";
    
                    // Load the image
                    HANDLE Handle_Bitmap_B = (HBITMAP)LoadImage(GetModuleHandle(nullptr), imageFile_B, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    
                if(!Handle_Bitmap_B)
                    {
                        // Handle error here
                        return;
                    }
    
            //----------------------------------------------------------------------
            // END     Load the image files
            //----------------------------------------------------------------------
    
    
    
            //----------------------------------------------------------------------
            // START   Create Region from imageFile_B
            //----------------------------------------------------------------------
    
                HRGN TemporaryRegion_for_Bitmap_B;
                HRGN FinalTransparentRegionFromBitmap_B;
    
    
                // Get information about the bitmap..
                GetObject(Handle_Bitmap_B, sizeof(bmpInfo), &bmpInfo);	// Get info about the bitmap
    
                // Select the bitmap into the dc
                hGdiObj = SelectObject(hdcMem, Handle_Bitmap_B);
    
                // Create a region from a bitmap with transparency colour of white
                // change the pixel values for a different transparency color
                // example - RGB(0,0,0) will mean a transparency color of black.. so the areas
                // of the bitmap not used to create the window will be black
                // COLORREF crTransparent = RGB(255, 255, 255);
                crTransparent = RGB(255, 255, 255);
    
    
                iX = 0;
                iY = 0;
                iRet02 = 0;     // For region 2
    
                FinalTransparentRegionFromBitmap_B = CreateRectRgn(0,0,0,0);
    
                for (iY = 0; iY < bmpInfo.bmHeight; iY++)
                    {
                        do
                        {
                            // Skip over transparent pixels at start of lines.
                            while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) == crTransparent)
                                iX++;
    
                            // Remember this pixel
                            int iLeftX = iX;
    
                            // Now find first non transparent pixel
                            while (iX < bmpInfo.bmWidth && GetPixel(hdcMem, iX, iY) != crTransparent)
                                ++iX;
    
                            // Create a temp region on this info
                            TemporaryRegion_for_Bitmap_B = CreateRectRgn(iLeftX, iY, iX, iY+1);
    
                            // Combine into main region.
                            // From wingdi.h
                            // WINGDIAPI int WINAPI CombineRgn(HRGN,HRGN,HRGN,int);
                            // Combine Region1 & Region2 & store result in ResultRegion.
                            // CombineRgn(ResultRegion,Region1,Region2,RGN_AND);
                            iRet02 = CombineRgn(FinalTransparentRegionFromBitmap_B, FinalTransparentRegionFromBitmap_B, TemporaryRegion_for_Bitmap_B, RGN_OR);
    
    
    
                        }
    
                        while(iX < bmpInfo.bmWidth);
                        {
                            iX = 0;
                        }
                    }
    
    
                // Center it on current desktop
                iRet02 = SetWindowRgn(FunctionReferenceTo_DialogBox01, FinalTransparentRegionFromBitmap_B, TRUE);
    
                    if(!iRet02)
                        {
                            return;
                        }
    
                    iX = (GetSystemMetrics(SM_CXSCREEN)) / 3 - (bmpInfo.bmWidth / 3);
    
                    iY = (GetSystemMetrics(SM_CYSCREEN)) / 3 - (bmpInfo.bmHeight / 3);
    
                    iRet02 = SetWindowPos(FunctionReferenceTo_DialogBox01, HWND_TOPMOST, iX, iY, bmpInfo.bmWidth, bmpInfo.bmHeight, 0);
    
            //----------------------------------------------------------------------
            // END     Create Region from imageFile_B
            //----------------------------------------------------------------------
    
    
    
            // Copy the memory dc into the screen dc
            paintRegion();
    
            // Delete the bitmap
            DeleteObject(Handle_Bitmap_B);
    
    
        }   //void createRegion_B(HWND FunctionReferenceTo_DialogBox01)
    
    
    
    
    
    
    
    
    
    
    void paintRegion()
    {
    	// Transfer color data from the source device context to the destination device context
    	BitBlt(hdcDest, 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, hdcMem, 0, 0, SRCCOPY);
    	UpdateWindow(Handle_MainWindow);
        RedrawWindow(Handle_MainWindow, nullptr, nullptr, RDW_UPDATENOW);
    
    }
    ------------------------------

    resource.h

    Code:
    #ifndef IDC_STATIC
        #define IDC_STATIC (-1)
    #endif
    
    #ifndef _UNICODE
        #define _UNICODE
    #endif // _UNICODE
    
    #ifndef UNICODE
        #define UNICODE
    #endif // UNICODE
    
    
    #define IDD_DIALOG1                     101
    ------------------------------

    resource.rc

    Code:
    #ifndef IDC_STATIC
        #define IDC_STATIC (-1)
    #endif
    
    #ifndef _UNICODE
        #define _UNICODE
    #endif // _UNICODE
    
    #ifndef UNICODE
        #define UNICODE
    #endif // UNICODE
    
    
    #include <windows.h>
    #include <commctrl.h>
    //#include <richedit.h>
    #include "resource.h"
    
    
    LANGUAGE 0, SUBLANG_NEUTRAL
    1                  RT_MANIFEST    ".\\manifest.xml"
    
    
    //----------
    
    IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95
    
    STYLE DS_SYSMODAL | WS_POPUP | WS_VISIBLE
    //CAPTION "Hello"  //Any setting of this Dialog's Caption (including blank "") seems to makes this dialog not be shaped correctly.
    {
    }
    ------------------------------

    manifest.xml

    (Put in your own codeblocks public key token at the xxxxxxxxxx area.

    Code:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <dependency>
        <dependentAssembly>
          <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="xxxxxxxxxx" language="*"/>    </dependentAssembly>
      </dependency>
      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
          <requestedPrivileges>
            <requestedExecutionLevel
              level="asInvoker"
              uiAccess="false"/>
          </requestedPrivileges>
        </security>
      </trustInfo>
    </assembly>

    ------------------------------


    Here is what I get:

    [ATTACH]a.bmp[/ATTACH]
    [ATTACH]b.bmp[/ATTACH]
    [ATTACH]c.bmp[/ATTACH]
    [ATTACH]d.bmp[/ATTACH]
    [ATTACH]e.bmp[/ATTACH]

    The attach stuff does not seem to work in the preview mode. I hope it shows up in on the page.
    Attached Files
  • SmithAnchorWork
    New Member
    • Mar 2020
    • 18

    #2
    I explained this to some extent in another post https://bytes.com/topic/c/answers/97...rolled-regions .

    Summery: Use buffers. You should be able to save the buffer as a final bitmap if you like, or keep it in your program for later use.

    Comment

    Working...