C++11 Seperately controlled regions

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

    C++11 Seperately controlled regions

    In C++11, using codeblocks 17.12, using GNU GCC Compiler, using UNICODE, on Windows XP Professional 32 bit with service pack 2. How do I make the three separate regions work independently of each other as described in the following? Not Visual Studio. Not ".net". Not C#.

    If I have three simple images "a.bmp", "b.bmp", "c.bmp";
    and I want them to each be regions with the white part not included;
    and I want to be able to move each around on the screen independent of the others;
    and I want the blue one to remain in front;
    and I want the red one and the green one to be in front of each other when I right-mouse-click on them, but not in front of the blue one; I am trying to do this with Dialog boxes.
    then how do I do this?

    I have tried a lot of examples and book instructions, and now I want better help.
  • rollerbladegirl
    New Member
    • Jan 2020
    • 69

    #2
    Here is where I am:

    Code:
    #ifndef IDC_STATIC
        #define IDC_STATIC (-1)
    #endif
    
    #ifndef _UNICODE
        #define _UNICODE
    #endif // _UNICODE
    
    #ifndef UNICODE
        #define UNICODE
    #endif // UNICODE
    
    // Not clear on if I need both _UNICODE and UNICODE .
    
    #include "resource.h"
    
    #include <windows.h>
    //#include <commctrl.h>   // Not clear on if I need this .
    
    #define MAX_LOADSTRING 100
    
        // Global Variables:
    
            HINSTANCE InstanceHandleOfMainWindow;	// Instance handle of the main window
    
            TCHAR szTitle[MAX_LOADSTRING];			// The title bar text
                // Why all the extra code for this? Why not just put the title directly into where the window is created?
                // Why not make smaller code without this extra loadstring etc.?
    
            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)";
    
        // Forward declarations of functions included later in this code module:
    
            ATOM				RegisterTheMainWindowClass(HINSTANCE hInstance2);
                // Why rip this out of the WinMain and make a big deal of it? Why not just leave it in winMain?
    
            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(HWND);
    
        // Empty Function to be used later to paint window regions.
    
            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;
    
        }   //int APIENTRY WinMain(HINSTANCE hInstance1, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    
    
    ATOM RegisterTheMainWindowClass(HINSTANCE hInstance3)
    
        // An ATOM is (always?) 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's value is completely opaque to user-mode. (whatever that means)
            // 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			= 0; // 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);
    
        }   //ATOM RegisterTheMainWindowClass(HINSTANCE hInstance3)
    
    BOOL DidTheMainWindowClassRegisterCorrectly(HINSTANCE hInstance4, int nCmdShow)
        {
            InstanceHandleOfMainWindow = hInstance4; // Store the instance handle in a previously created global variable
    
            Handle_MainWindow = CreateWindow(   // Should I use CreateWindowEx ?
                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(Handle_DialogBox2);
    
            // Don't have to show or update the window ?
            // ShowWindow(hWnd, nCmdShow);
            // UpdateWindow(hWnd);
    
            return TRUE;
    
        }   //BOOL DidTheMainWindowClassRegisterCorrectly(HINSTANCE hInstance4, int nCmdShow)
    
    
    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;
    
        }   // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    
    
    INT_PTR CALLBACK DialogProc(HWND Handle_DialogBox01, UINT uMsg, WPARAM wParam, LPARAM lParam )
                // 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:
                    {
                        paintRegion();
                    }
                    return TRUE;
                    break;
    
    
                case WM_LBUTTONDOWN:
                    {
                        mouseState = 1;
                    }
                    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;
    
        }   // INT_PTR CALLBACK DialogProc( HWND Handle_DialogBox01, UINT uMsg, WPARAM wParam, LPARAM lParam )
    
    void createRegion(HWND FunctionReferenceTo_DialogBox01)
        {
    
            COLORREF crTransparent;
    
            int iX = 0;
            int iY = 0;
    
            int iRet01 = 0;     // Integer For region 1
            int iRet02 = 0;     // Integer For region 2
    
    
            // Get the destination device context
            hdcDest = GetDC(FunctionReferenceTo_DialogBox01);
    
            // Create a memory DC
            hdcMem = CreateCompatibleDC(nullptr);
    
    
            //----------------------------------------------------------------------
            // 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;
                        }
    
    
                // 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_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);
                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;     // For region 2
    
                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
            //----------------------------------------------------------------------
    
    
    //----------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------
    //----------------------------------------------------------------------------------------------------
    
    
            //----------------------------------------------------------------------
            // 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
                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_A);
            DeleteObject(Handle_Bitmap_B);
    
        }   // void createRegion(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);
    }
    Last edited by gits; Jan 3 '20, 04:11 PM. Reason: added code tags

    Comment

    • rollerbladegirl
      New Member
      • Jan 2020
      • 69

      #3
      Here are some pictures showing what I am doing:
      Attached Files

      Comment

      • rollerbladegirl
        New Member
        • Jan 2020
        • 69

        #4
        Thank you gits for fixing the code to show indentations, etc. That was nice of you. I shall try to post code correctly formatted for viewing in the future. I copy and pasted this code, but that was not sufficient. You fixed it. Thank you. I shall try to do better next time.


        Also. I have been experimenting and got the code to work better in that it shows both of the images, but it greys out one of them. Should I replace the original code with the updated code in my original posting, or post it separately?
        Last edited by rollerbladegirl; Jan 3 '20, 07:12 PM. Reason: Thanks for the help.

        Comment

        • rollerbladegirl
          New Member
          • Jan 2020
          • 69

          #5
          So far, to date 1/8/2020, this post has been viewed 224 times. Still no one told me how to do this. I need some help. C++ is new to me. Please someone tell me how to do this. I can create a region. I can create two regions, one at a time. I do not have to do this with dialog boxes if there is another or better/faster way. Help! Please.

          Comment

          • SmithAnchorWork
            New Member
            • Mar 2020
            • 18

            #6
            In Microsoft Windows:
            Do not use dialog boxes.
            "I am trying to do this with Dialog boxes."

            If you use standard dialog boxes then you are adding another window handle to your program. That allows Microsoft to add bloat to your program. Try to avoid adding any and all "additional " window handles to your program if you can. Sometimes it is necessary, but work at not having them.

            You are working with images, therefore stay with images and use mouse tracking to detect when your mouse is over each of the images.

            Since you are using regions then you might already have somewhere in your code the x and y positions of the entire pixel layout of each of your images. Your current front image's pixels would be subtracted from any and all images behind it. Your most rearward image would have all forward image pixels subtracted from it. Track you mouse position. Detect when the mouse is over a specific image. If a click occurs then respond as though it were a click on that image.

            Start with creating two buffers.
            1. Initialize the back most buffer.
            2. Place all of your images on that buffer from back most image to front most image.
            3. Initialize the front most buffer.
            4. Do your image manipulation in the back most buffer.
            5. Copy that buffer to the front buffer.
            6. Copy that buffer to the screen.

            You now have your image manipulation in buffers and not directly to the screen. Thus, less chance for screen flickering.

            You now have two buffers that you can work with. The back most buffer you are currently using. The front most buffer is already set up, but not being actively used, and ready for testing later use. With the extra buffer you have an expansion option already built in. Example: you might want to do some testing of image effects and you do not want to damage your existing code, so do the testing in the front buffer where you can delete the entire test however complicated and intricate it is without it being tightly integrated into your current (back-most buffered) code.

            Maybe, if someone has the time they might give you the code to do this, or maybe if later I have the time I might strip some out of one of my programs. But, this is how it can be done.

            I see that you are using XP sp2. Since you are knowledgeable about the security of why to not use beyond that, then I expect that you might know at least some of the security of why to avoid using a lot of un-necessary Windows handles.

            Going through the process again so that you understand what I am saying:

            Buffers;

            Images to buffers;

            Mouse to pixel location detection;

            Respond with rebuilding the back most buffer with images in the order that you want back most to front most.

            Then copy back buffer to front buffer.

            The next two things should be in one thread with no delays in between them. Not in two separate threads!
            • Re-analyze your mouse positioning. You are doing this part again BEFORE PLACING THE FRONT BUFFER TO THE SCREEN: Configure your tracking for the mouse position for the new image setup positions. No responses yet. Just set up the tracking for the new image placement.
            • Then copy the front buffer to the screen.


            The user sees the screen.

            Comment

            Working...