triumphost 120 Posting Whiz

Everytime you do GetDC, you are leaking a DC. You NEED to ReleaseDC.

Even if you do DC = GetDC(NULL) you need to do ReleaseDC(NULL, DC);. If you do DC = GetDC(hwnd) you need to do ReleaseDC(hwnd, DC);.

In the above code, you don't need GetDC.. Use the DC that is inside the PaintStruct.

Secondly, for usage with menu, it must be COMPATIBLE.. You can't just use CreateBitmap and hope that the DC's compatible..

HBITMAP bitmap(image imgImage) //creates a copy of imgImage or whatever is passed to this function! Beware!
{
    BITMAP bm;
    GetObject((HBITMAP)imgImage, sizeof(bm), &bm);

    HDC DC = GetDC(NULL);
    HDC MemDCExercising = CreateCompatibleDC(DC); //Create a DC compatible with our Display/Monitor.. 32-bit.
    HBITMAP outbitmap = CreateCompatibleBitmap(DC, bm.bmWidth, bm.bmHeight); //create a bitmap that is compatible with our DC.
    HBITMAP oldbitmap = (HBITMAP) SelectObject(MemDCExercising, outbitmap);


    DrawHBITMAPtoHDC(imgImage, MemDCExercising); //good.

    SelectObject(MemDCExercising, oldbitmap);
    DeleteDC(MemDCExercising);
    ReleaseDC(NULL, DC); //good.

    HMENU hMenu = NULL;
    if(primeiromenu)
        hMenu = mnuBar;
    else
        hMenu = MenuHandle;
    SetMenuItemBitmaps(hMenu,ID,MF_BYCOMMAND,(HBITMAP)outbitmap ,(HBITMAP)outbitmap);

    return outbitmap; //we return it so that later we can call DeleteObject to free its memory.
}

The only thing I'm not sure about is if the DrawHBITMAPToHDC call will work. But try it and let me know.

triumphost 120 Posting Whiz

The first thing you need to do is select the HBITMAP into a MemoryDC. Then you cna use the AlphaBlend function to draw it to the WindowDC.

If the MemoryDC is NOT compatible with the WindowDC, this will fail! In that case, you can use CreateCompatibleBitmap(WindowDC, width, height), copy the existing bitmap to the new bitmap, draw it and free the new bitmap.

However, that is left as an exercise for you..

void DrawAlphaGDI(HDC DC, Gdiplus::Rect rect)
{
    HGDIOBJ obj = SelectObject(memDC, hBmp);
    AlphaBlend(DC, rect.X, rect.Y, rect.Width, rect.Height, memDC, 0, 0, Width, Height, BlendFunc); //You need to create a blend-function..
    SelectObject(memDC, obj);
}

If the source has no alpha channel, it will NOT be transparent unless you specify what colour to make transparent. For that, you can use TransparentBlt.

Image <-- Transparent image (png)

Results <-- Transparent Drawing..

triumphost 120 Posting Whiz

The term you are looking for is called "OCR".. Optical Character Recognition.

A library that may help, would be OpenCV (an image recognition library).

triumphost 120 Posting Whiz

You ARE leaking even if you think you aren't. It might be very slight but by not deleting resources you allocate, you are indeed leaking them.

No matter what, you need to free any resource you allocated. I stated already that you need to check in your setters and getters that you do not overwrite memory allocated objects before freeing them. Something which you are still doing.

Also, you are invoking undefined behaviour by not doing the above.. Finally, your HBITMAP is deleted in the destructor so you need to make sure that your class is alive and well until you no longer need any of its resources.. This includes the HBITMAP. When your class dies, so does the HBITMAP.

a. You are using hdcImage without allocating it in your constructor.. How can you use it in the constructor or anywhere else, if it's NULL.

b. In your SelectFrame function, you are using img but you have no idea if img exists or not. Why? Because in your other constructors, img is never allocated. It's NULL or undefined. You only have one constructor that allocates img and your SelectFrame function will only be valid if that one constructor is used. All other constructors will cause your SelectFrame function to invoke undefined behaviour..

c. What I meant by freeing and allocating resources properly is an example of the following re-write of your class (which I did not test):

YourClass.h:

#ifndef AUTOGDI_H_INCLUDED
#define AUTOGDI_H_INCLUDED

#include <windows.h>
#include <gdiplus.h>

class AutoGDI
{ …
cambalinho commented: thank you +3
triumphost 120 Posting Whiz

That's a LOT of code just for one simple task: getting an hbitmap from an hdc..

Your code leaks because.. You need lessons in memory management.. Or at least, guidance. You really really need to take care of your code more carefully.

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

a. In your constructors, you are doing:

btBimap = CreateBitmap(w, h, 1, 32, NULL);

But in your destructor, you have NEVER deleted it with DeleteObject(btBtmap).

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

b. You never re-select the OldBitmap back into the DC at all! In the constructor you are doing:

SelectObject(hdcimage, btBimap); which needs to be: HGDIOBJ obj = SelectObject(hdcimage, btBimap);

then in the destructor you need to do: SelectObject(hdcimage, obj) and THEN you can delete the btBitmap. Either that or select it right back in after you finish using it.. That way you don't need to do it in the destructor.. Not sure why you need to keep it selected in the first place.

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

c. You are doing: HCURSOR hicon = (HCURSOR)LoadImage(NULL, path, IMAGE_CURSOR, w, h, ....);

But you NEVER delete the hicon..

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

d. You are doing: GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count); TWICE but you NEVER call free(pDimensionIDs) even once.

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

e. You are doing: graphic = new Graphics(hdcimage); but you NEVER delete graphic; anywhere. In your "set" function, you never bother to check if it already exists either.. So even if you delete it in your destructor, calling set twice will cause it to leak anyway.. You need to call delete before you set it. And call delete in the …

cambalinho commented: thanks for all +0
triumphost 120 Posting Whiz

Have you tested your code? The way I do it is:

HBITMAP hBmp = reinterpret_cast<HBITMAP>(GetCurrentObject(DC, OBJ_BITMAP));
triumphost 120 Posting Whiz

There's multiple ways to do it.. First the manual way:

1:

union KeyState
{
    LPARAM lparam;

    struct
    {
        unsigned nRepeatCount : 16;
        unsigned nScanCode : 8;
        unsigned nExtended : 1;
        unsigned nReserved : 4;
        unsigned nContext : 1;
        unsigned nPrev : 1;
        unsigned nTrans : 1;
    };
};


LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int special = 0;

    switch(message)
    {
        case WM_KEYUP:
        {
            bool stored = false;
            KeyState state;
            state.lparam = lParam;
            if(state.nExtended)
            {
                special = wParam;
                stored = true;
            }

            switch(wParam)
            {
                case VK_CONTROL:
                case VK_RCONTROL:
                case VK_SHIFT:
                case VK_RSHIFT:
                case VK_MENU:
                    special = wParam;
                    stored = true;
                    break;
            }

            if(!stored)
            {
                switch(special)
                {
                    case VK_CONTROL:
                    case VK_RCONTROL:
                        std::cout<<"CONTROL + "<<(char)(wParam)<<"\n";
                        special = 0;
                        break;
                    case VK_SHIFT:
                    case VK_RSHIFT:
                        std::cout<<"SHIFT + "<<(char)(wParam)<<"\n";
                        special = 0;
                        break;
                    case VK_MENU:
                        std::cout<<"ALT + "<<(char)(wParam)<<"\n";
                        special = 0;
                        break;

                    default:
                        std::cout<<(char)wParam<<"\n";
                        special = 0;
                        break;
                }
                break;
            }
        }
        break;

        case WM_SYSKEYDOWN:
        {
            special = wParam;
        }
        break;

    }
}

and then the easy way:

2:

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
        case WM_KEYUP:
        {
            bool is_special = false;
            if((GetAsyncKeyState(VK_LCONTROL) & 1) || (GetAsyncKeyState(VK_CONTROL) & 1) || (GetAsyncKeyState(VK_RCONTROL) & 1))
            {
                std::cout<<"CONTROL";
                is_special = true;
            }

            if((GetAsyncKeyState(VK_LSHIFT) & 1) || (GetAsyncKeyState(VK_SHIFT) & 1) || (GetAsyncKeyState(VK_RSHIFT) & 1))
            {
                if(is_special)
                    std::cout<<" + ";
                std::cout<<"SHIFT";
                is_special = true;
            }

            if(GetAsyncKeyState(VK_MENU) & 1)
            {
                if(is_special)
                    std::cout<<" + ";
                std::cout<<"ALT";
                is_special = true;
            }

            switch(wParam)
            {
                case VK_CONTROL:
                case VK_LCONTROL:
                case VK_RCONTROL:
                case …
triumphost 120 Posting Whiz

Here try this.. It's very hard to explain so hopefully you can understand it by seeing the code:

Menu-Class CodeBlocks Example

It works like this:

When you create a menu, you want to set it to MNS_NOTIFYBYPOS. This means you'll get WM_MENUCOMMAND, WM_SYSCOMMAND, WM_INITMENUPOPUP, WM_UNINITMENUPOPUP, WM_MENUSELECT.

WM_MENUCOMMAND will let you know when a menu is "clicked".
WM_SYSCOMMAND will let you know when a system menu is "clicked".
WM_INITMENUPOPUP will let you know when any menu has been "opened".
WM_UNINITMENUPOPUP will let you know when any menu has been "closed".
WM_MENUSELECT will let you know when any menu has been "hovered" over.

Now when creating each menu, I added the "this" pointer to the MenuInfo.dwMenuData.

I also added the "this" pointer to the MenuItemInfo.dwItemData.

That means that every time you get any of the above events, you can read BOTH the MenuInfo.dwMenuData or the MenuItemInfo.dwItemData to get a handle to your class instance..

That is quite wonderful because it becomes quite easy to make Object-Oriented Menus and call EventHandlers on the corresponding menu.

Another thing that I did was generate some ID's for the controls. I did this so that I can store the ID into the menu's MenuItemInfo.wID field. Why? Because if I don't do that, all popup menus will have the "handle" as the "ID". That's not convenient for us because we want to keep all menus consistent.

We use the ID to identify the exact menu rather than by position. We use the HMENU to retrieve …

cambalinho commented: thanks for all my friend +3
triumphost 120 Posting Whiz

You're not handling the LOWORD or HIWORD properly.. You seem to be mis-interpretting it.

You cannot just ASSUME that the menu is stored in lParam because that's incorrect. lParam can be NULL (when the menu is closed). lParam can be another menu that is NOT yours.

You need to check the state of WPARAM then check lParam and see if it is your menu. Finally, you can check the state of your menu. An example (I use ID's.. it could be an HMENU depending on your menu setup) is shown below:

#define MENU_ID 0x01   

#include <tchar.h>
#include <windows.h>
#include <iostream>

LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);

TCHAR szClassName[] = _T("CodeBlocksWindowsApp");

int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    HWND hwnd;
    MSG messages;

    WNDCLASSEX wincl;
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof(WNDCLASSEX);
    wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if(!RegisterClassEx(&wincl))
        return 0;

    hwnd = CreateWindowEx(0, szClassName, _T("Code::Blocks Template Windows App"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
    ShowWindow(hwnd, nCmdShow);

    while(GetMessage(&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return messages.wParam;
}

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{    
    switch(message)
    {
        case WM_CREATE:
        {
            HMENU menu = GetSystemMenu(hwnd, false);
            InsertMenu(menu, 0, MF_BYPOSITION | MF_STRING, MENU_ID, "My Custom Menu");
        }
        break;

        case WM_SYSCOMMAND:
        {
            switch(wParam)
            {
                case MENU_ID:
                    MessageBox(NULL, "My Custom Menu Clicked", "Notice", 0);
                    break;

                default:
                    return …
triumphost 120 Posting Whiz

Works fine as far as I can tell.. You need to give more details or show code.

#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif

#include <tchar.h>
#include <windows.h>

LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);

TCHAR szClassName[] = _T("CodeBlocksWindowsApp");

int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    HWND hwnd;
    MSG messages;

    WNDCLASSEX wincl;
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;
    wincl.style = CS_DBLCLKS;
    wincl.cbSize = sizeof(WNDCLASSEX);
    wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;
    wincl.cbClsExtra = 0;
    wincl.cbWndExtra = 0;
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if(!RegisterClassEx(&wincl))
        return 0;

    hwnd = CreateWindowEx(0, szClassName, _T("Code::Blocks Template Windows App"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, HWND_DESKTOP, NULL, hThisInstance, NULL);
    ShowWindow(hwnd, nCmdShow);

    while(GetMessage(&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return messages.wParam;
}

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_CREATE:
        {
            HMENU menu = GetSystemMenu(hwnd, false);
            InsertMenu(menu, 0, MF_BYPOSITION | MF_STRING, 1, "My Custom Menu");
        }
        break;

        case WM_SYSCOMMAND:
        {
            switch(wParam)
            {
                case 1:
                    MessageBox(NULL, "My Custom Menu Clicked", "Notice", 0);
                    break;

                case SC_MINIMIZE:
                    MessageBox(NULL, "Minimise Clicked", "Notice", 0);
                    //break;

                default:
                    return DefWindowProc(hwnd, message, wParam, lParam);
            }
        }
        break;

        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
    }

    return 0;
}
cambalinho commented: your code give me that idea... thanks for all +3
triumphost 120 Posting Whiz

You should be receiving an event for WM_MENUCOMMAND or WM_COMMAND when the Menu is clicked. If nothing is clicked, you receive nothing.

triumphost 120 Posting Whiz

After you do the WM_MENUITEMPOPUP, go through that menu and check with GetMenuState:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms647982(v=vs.85).aspx

If it returns: MF_HILITE, the mouse is over that item.

triumphost 120 Posting Whiz

You need to create a Real-Time-Message-Loop as done in Direct-X. See: http://www.directxtutorial.com/Lesson.aspx?lessonid=9-1-4

while(true)
{
    while(PeekMessage(&messages, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }

    if (messages.message == WM_QUIT)
        break;

    //Do Drawing Here instead of WM_PAINT..
}
triumphost 120 Posting Whiz
/*
    Creates a "Bitmap" on the heap so you can explicitly delete it
    before shutting down. Otherwise you must wait until it goes out of
    scope before shutting down.
*/
HBITMAP loadBitmap(const wchar_t* path)
{
    HBITMAP tBmp = NULL;
    ULONG_PTR token = 0;
    Gdiplus::GdiplusStartupInput input = NULL;
    Gdiplus::GdiplusStartup(&token, &input, NULL);

    if (token != 0)
    {
        Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(path);
        bmp->GetHBITMAP(Gdiplus::Color::Transparent, &tBmp);
        delete bmp;
        Gdiplus::GdiplusShutdown(token);
    }
    return tBmp;
}


/*
    Loads a PNG into an HBITMAP and uses BM_SETIMAGE to set the image
    of a button.
*/
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HBITMAP tBmp = NULL;

    switch(message)
    {
        case WM_CREATE:
        {
            HWND btn = CreateWindow("BUTTON", "TEXT", BS_BITMAP | WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
                         100, 100, 95, 25, hwnd, (HMENU)1, NULL, NULL);


            tBmp = loadBitmap(L"C:/Users/Kira/Desktop/Test.png");
            SendMessage(btn, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)tBmp);
            ShowWindow(btn, SW_SHOW);
        }
        break;


    case WM_DESTROY:
        DeleteObject(tBmp);
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}
triumphost 120 Posting Whiz

sendinput

mouse_event

Use SendInput or mouse_event for Windows.

cambalinho commented: thanks +3
triumphost 120 Posting Whiz

The HWND parameter is a handle to the window that owns the menu..

PostMessage(ApplicationWindowHandle, WM_COMMAND, MenuID, 0);

will work.

Example (You can use this if you like but I don't recommend doing it this "exact" way [specifically the "FindMenuItem" part]):

#include <windows.h>
#include <string>
#include <vector>
#include <tchar.h>
#include <iostream>

class MenuBar
{
    private:
        HMENU ID;
        HWND Parent;
        std::vector<HMENU> Menus;

    public:
        MenuBar();
        MenuBar(const MenuBar &M) = delete;
        MenuBar(HWND Parent);
        virtual ~MenuBar();

        std::string GetText(HMENU Menu, int Position);
        HMENU FindMenuItem(std::string MenuName);
        HMENU FindMenuItem(HMENU Parent, std::string MenuName);

        void CreateSubMenu(HMENU Parent, std::string Name, DWORD Style);
        void AddMenuItem(std::string Name, DWORD Style);
        void AppendMenuItem(HMENU Parent, std::string Name, DWORD Style);

        HWND GetParent() const;
        void Show();

        MenuBar& operator = (const MenuBar &M) = delete;
};

MenuBar::~MenuBar() {}

MenuBar::MenuBar() : ID(nullptr), Parent(nullptr), Menus() {};

MenuBar::MenuBar(HWND Parent) : ID(nullptr), Parent(Parent), Menus()
{
    Menus.push_back(CreateMenu());
}

std::string MenuBar::GetText(HMENU Menu, int Position)
{
    TCHAR Buffer[1024] = {0};
    MENUITEMINFO MenuInfo = {0};
    MenuInfo.cbSize = sizeof(MenuInfo);
    MenuInfo.fMask = MIIM_TYPE;
    MenuInfo.fType = MFT_STRING;
    MenuInfo.cch = sizeof(Buffer);
    MenuInfo.dwTypeData = Buffer;
    if (GetMenuItemInfo(Menu, Position, true, &MenuInfo))
    {
        return Buffer;
    }
    return std::string();
}

HMENU MenuBar::FindMenuItem(std::string MenuName)
{
    for (std::size_t I = 0; I < Menus.size(); ++I)
    {
        if (MenuName == GetText(Menus.front(), I))
        {
            return GetSubMenu(Menus.front(), I);
        }
    }
    return nullptr;
}

HMENU MenuBar::FindMenuItem(HMENU Parent, std::string MenuName)
{
    std::size_t Count = GetMenuItemCount(Parent);
    for (std::size_t I = 0; I < Count; ++I)
    {
        if (MenuName == GetText(Parent, I))
        {
            return GetSubMenu(Parent, I);
        }
    }
    return nullptr;
}

void MenuBar::CreateSubMenu(HMENU Parent, std::string Name, DWORD Style)
{
    Menus.push_back(CreatePopupMenu());
    AppendMenu(Parent, …
triumphost 120 Posting Whiz

Is this Visual Studio C++? C++/CLI? I ask because you have "property" and "get, set" syntax which matches that of C#..

triumphost 120 Posting Whiz

If you know the resource ID, you can extract them with WinAPI. I don't know about extracting them using QT.

triumphost 120 Posting Whiz

Are you able to NOT use borland and use gcc/g++ or MSVC?

triumphost 120 Posting Whiz

The problem with the above code is actually that you LOAD the image every single time the window is painted. This can take time to do. Not only that, you never delete the compatible dc or bitmap that you created and so you are leaking in the above code. It could be that you are also doing other resource intensive code in the paint or resize messages.

Is your image not drawing at all? Is it flickering?

Other than that, I cannot replicate it.

This works just fine for me:

class Form2 : public BaseForm
{
    private:
        std::function<void(HWND, HDC)> onPaint;

    public:
        Form2(const char *Title, POINT Location, unsigned short Width, unsigned short Height, HWND Parent = NULL);
        LRESULT WinProc(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam);
        int Show();
        HWND GetHWND() {return BaseForm::GetHWND();}

        void setPaintListener(const std::function<void(HWND, HDC)>& onPaint) {this->onPaint = onPaint;}
};

Form2::Form2(const char *Title, POINT Location, unsigned short Width, unsigned short Height, HWND Parent)
{
    BaseForm::Create(0, Title, WS_OVERLAPPEDWINDOW | WS_TABSTOP, Location, Width, Height, Parent);
}

LRESULT Form2::WinProc(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
        case WM_PAINT:
        {
            PAINTSTRUCT ps = {0};
            HDC hdc = BeginPaint(Hwnd, &ps);

            if (onPaint)
            {
                onPaint(Hwnd, hdc);
            }

            EndPaint(Hwnd, &ps);
        }
        break;

        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;

        default:
            return DefWindowProc(Hwnd, Msg, wParam, lParam);
    }
    return 0;
}

int Form2::Show()
{
    MSG Messages = {0};
    ShowWindow(this->GetHWND(), SW_SHOW);

    while(GetMessage(&Messages, NULL, 0, 0))
    {
        TranslateMessage(&Messages);
        DispatchMessage(&Messages);
    }
    return Messages.wParam;
}

int main()
{
    Form2 f("Hello", {CW_USEDEFAULT, CW_USEDEFAULT}, 500, 500);

    //Load the image once.. you can do …
cambalinho commented: thanks anyway +3
triumphost 120 Posting Whiz

I cannot replicate this. What does your WndProc look like?

triumphost 120 Posting Whiz

The only way to skin and draw child controls is to use the BS_OWNERDRAW flag and draw the control yourself.

triumphost 120 Posting Whiz

If using Windows:

`PlaySound("MyFile.wav", NULL, SND_FILENAME);`

//or:

`PlaySound("MyFile.wav", NULL, SND_FILENAME | SND_ASYNC);`

For linux you can play files by opening /dev/dsp and writing the file to it.

You could also use system and call aplay to play it.

triumphost 120 Posting Whiz

I think this is the guy from stack overflow that told me he could not change his code when I offered him code that reads a bitmap and finds it on screen :l

Again, you are missing the padding at the end of each bitmap scan line.

Here is how to read a 24-bit bitmap (without std::fstream):

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct bitmap
{
    unsigned int width, height;
    unsigned char *pixels;
};

struct bitmap* bmp;

void FreeBmp()
{
    if (bmp && bmp->pixels)
    {
        bmp->width = 0;
        bmp->height = 0;
        free(bmp->pixels);
        free(bmp);
        bmp = NULL;
    }
}

bool LoadBmp(const char *filepath)
{
    bmp = NULL;
    FILE *f = fopen(filepath, "rb");

    if (f)
    {
        bmp = malloc(sizeof(bitmap));
        bmp->width = 0;
        bmp->height = 0;
        bmp->pixels = NULL;

        unsigned char info[54] = {0};
        fread(info, sizeof(unsigned char), 54, f);

        bmp->width = *(unsigned int *)&info[18];
        bmp->height = *(unsigned int *)&info[22];

        unsigned int size = ((((bmp->width * bmp->height) + 31) & ~31) / 8) * bmp->height;
        bmp->pixels = malloc(size);
        fread(bmp->pixels, sizeof(unsigned char), size, f);
        fclose(f);

        for(int i = 0; i < size; i += 3)
        {
            unsigned char tmp = bmp->pixels[i];
            bmp->pixels[i] = bmp->pixels[i + 2];
            bmp->pixels[i + 2] = tmp;
        }
        return true;
    }

    return false;
}

int main()
{
    LoadBmp("/users/Brandon/Desktop/t.bmp");
    //....
    FreeBmp();
}
triumphost 120 Posting Whiz

If the sample works fine, why not use it? I doubt you need the colour to be white if you plan on making it transparent. You can have any colour as long as R isn't 0xFF aka 255. I wasn't able to figure out why.. It just seems to be that way.

triumphost 120 Posting Whiz

Ahh I see.. Apparently the problem is with Aero and hbrBackground being NULL as well as using Magenta (0xFF, 0x00, 0xFF) as the transparent colour. Try the following..

#include <windows.h>

LRESULT __stdcall WindowProcedure(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
        case WM_CREATE:
        {
            CreateWindow("BUTTON", "Btn", WS_VISIBLE | BS_PUSHBUTTON | WS_CHILD, 100, 100, 95, 25, Hwnd, (HMENU)1, nullptr, nullptr);
        }
        break;

        /*case WM_ERASEBKGND:
        {
            SetLayeredWindowAttributes(Hwnd, RGB(0x80,0x00, 0xFF), 0, LWA_COLORKEY);
        }
        return 1;*/


        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(Hwnd, Msg, wParam, lParam);
    }
    return 0;
}


int main()
{
    WNDCLASSEX FormClass;
    FormClass.cbSize        = sizeof(WNDCLASSEX);
    FormClass.style         = CS_DBLCLKS;
    FormClass.lpfnWndProc   = WindowProcedure;
    FormClass.cbClsExtra    = 0;
    FormClass.cbWndExtra    = 0;
    FormClass.hInstance     = GetModuleHandle(NULL);
    FormClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    FormClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    FormClass.hbrBackground = CreateSolidBrush(RGB(0x80, 0x00, 0xFF));
    FormClass.lpszMenuName  = NULL;
    FormClass.lpszClassName = "Class";
    FormClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassEx(&FormClass);
    HWND hwnd = CreateWindowEx(WS_EX_LAYERED, "Class", "Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, GetModuleHandle(NULL), NULL);
    SetLayeredWindowAttributes(hwnd, RGB(0x80, 0x00, 0xFF), 0, LWA_COLORKEY);

    MSG Messages = {0};
    ShowWindow(hwnd, SW_SHOW);

    while(GetMessage(&Messages, NULL, 0, 0))
    {
        TranslateMessage(&Messages);
        DispatchMessage(&Messages);
    }
    return Messages.wParam;
}
triumphost 120 Posting Whiz

Try this.. It has the transparent client area as shown in your picture with a clickable close button and clickable child button. Uses the Layered window as described in my first post on this thread.

#include <windows.h>

LRESULT __stdcall WindowProcedure(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
        case WM_CREATE:
        {
            CreateWindow("BUTTON", "Btn", WS_VISIBLE | BS_PUSHBUTTON | WS_CHILD, 100, 100, 95, 25, Hwnd, (HMENU)1, NULL, NULL);
        }
        break;

        case WM_ERASEBKGND:
        {
            SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
            SetLayeredWindowAttributes(Hwnd, GetSysColor(COLOR_WINDOW), 0, LWA_COLORKEY);
        }
        return 1;


        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(Hwnd, Msg, wParam, lParam);
    }
    return 0;
}


int main()
{
    WNDCLASSEX FormClass;
    FormClass.cbSize        = sizeof(WNDCLASSEX);
    FormClass.style         = CS_DBLCLKS;
    FormClass.lpfnWndProc   = WindowProcedure;
    FormClass.cbClsExtra    = 0;
    FormClass.cbWndExtra    = 0;
    FormClass.hInstance     = GetModuleHandle(NULL);
    FormClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    FormClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    FormClass.hbrBackground = NULL;
    FormClass.lpszMenuName  = NULL;
    FormClass.lpszClassName = "Class";
    FormClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassEx(&FormClass);
    HWND hwnd = CreateWindowEx(WS_EX_LAYERED, "Class", "Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, GetModuleHandle(NULL), NULL);
    SetLayeredWindowAttributes(hwnd, 0, 0xFF, LWA_ALPHA);

    MSG Messages = {0};
    ShowWindow(hwnd, SW_SHOW);

    while(GetMessage(&Messages, NULL, 0, 0))
    {
        TranslateMessage(&Messages);
        DispatchMessage(&Messages);
    }
    return Messages.wParam;
}
triumphost 120 Posting Whiz

I don't know what back colour you are trying to hide. My first solution works for fixing the focus. Other than that, I can't understand what it is you need fixing without seeing the code or a snippet of it or even a picture.

I can't figure out exactly what you are asking. :S

triumphost 120 Posting Whiz

I have no clue what you mean in this case. I'd need a picture or code to know what you mean.

triumphost 120 Posting Whiz

You need to implement it. Handle the WM_DESTROY message.

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:  //Not necessary. Nice to have though.
            DestroyWindow(hwnd); //Destroys the Window. Application does not have to quit.
            break;

        case WM_DESTROY: //Must have in order to close the window.
            PostQuitMessage(0); //Tells the application to quit.
            break;

        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    return 0;
}
triumphost 120 Posting Whiz

WS_EX_TRANSPARENT - Specifies that a window created with this style is to be transparent. That is, any windows that are beneath the window are not obscured by the window. A window created with this style receives WM_PAINT messages only after all sibling windows beneath it have been updated.

MSDN

It means that if you use this flag, the windows below yours will get all the messages. In other words, if you click on your window, the click does not register. Instead, the window below/behind yours will get the click and your window will no longer be in focus.

To fix this, do:

CreateWindowEx(0, Title, WS_.... | WS_...., .....);

Notice that the first parameter is NOT WS_EX_TRANSPARENT.

Then use:

void SetTransparency(HWND hwnd, std::uint8_t Transperancy)
{
    long wAttr = GetWindowLong(hwnd, GWL_EXSTYLE);
    SetWindowLong(hwnd, GWL_EXSTYLE, wAttr | WS_EX_LAYERED);
    SetLayeredWindowAttributes(hwnd, 0, Transperancy, 0x02);
}

The usage can be as such:

SetTransparency(MyWindow, 0xFF); //255 = Full / 100% opacity.
SetTransparency(MyWindow, 0xFF / 2); //Half / 50% transparent.
SetTransparency(MyWindow, 0x00); //Full transparency/invisible.

The reason this works is because you are changing the Window's style to WS_EX_LAYERED. A layered window can be transparent or opaque and optionally have child windows. You do NOT need WS_EX_TRANSPARENT.

If you set the transparency to 0x00, your window will NOT receive clicks because it is NOT drawn on screen. This is equivalent to hiding it or minimising it.

triumphost 120 Posting Whiz

Btw.. You can set: Info.bmiHeader.biSizeImage = Width * Height * (BitsPerPixel > 24 ? 4 : 3); to 0 instead. It'd auto calculate it for you. I just chose to show you how it actually does it (an approximation). The real calculation is done at line 38.. So it's better to set line 21 to 0 or remove it.

triumphost 120 Posting Whiz
#include <vector>
#include <fstream>
#include <cstring>
#include <windows.h>

bool HDCToFile(const char* FilePath, HDC Context, RECT Area, uint16_t BitsPerPixel = 24)
{
    uint32_t Width = Area.right - Area.left;
    uint32_t Height = Area.bottom - Area.top;

    BITMAPINFO Info;
    BITMAPFILEHEADER Header;
    memset(&Info, 0, sizeof(Info));
    memset(&Header, 0, sizeof(Header));
    Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    Info.bmiHeader.biWidth = Width;
    Info.bmiHeader.biHeight = Height;
    Info.bmiHeader.biPlanes = 1;
    Info.bmiHeader.biBitCount = BitsPerPixel;
    Info.bmiHeader.biCompression = BI_RGB;
    Info.bmiHeader.biSizeImage = Width * Height * (BitsPerPixel > 24 ? 4 : 3);
    Header.bfType = 0x4D42;
    Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);


    char* Pixels = NULL;
    HDC MemDC = CreateCompatibleDC(Context);
    HBITMAP Section = CreateDIBSection(Context, &Info, DIB_RGB_COLORS, (void**)&Pixels, 0, 0);
    DeleteObject(SelectObject(MemDC, Section));
    BitBlt(MemDC, 0, 0, Width, Height, Context, Area.left, Area.top, SRCCOPY);
    DeleteDC(MemDC);

    std::fstream hFile(FilePath, std::ios::out | std::ios::binary);
    if (hFile.is_open())
    {
        hFile.write((char*)&Header, sizeof(Header));
        hFile.write((char*)&Info.bmiHeader, sizeof(Info.bmiHeader));
        hFile.write(Pixels, (((BitsPerPixel * Width + 31) & ~31) / 8) * Height);
        hFile.close();
        DeleteObject(Section);
        return true;
    }

    DeleteObject(Section);
    return false;
}

int main()
{
    HWND win = GetDesktopWindow();
    HDC dc = GetDC(win);
    HDCToFile("C:/.../Desktop/Foo.bmp", dc, {0, 0, 1366, 768});
    ReleaseDC(win, dc);
}
triumphost 120 Posting Whiz

Beware of my complicated suggestion below.. but it is a good way to do it in my opinion:

Create event listeners..

The way it works it that you can subscribe to an event and unsubscribe. For implementation, you can call "Notify" and it will call the right function for you.

An example for the MouseListener would be:

class MouseListener : public IEventListener
{
    public:
        MouseListener();
        virtual ~MouseListener() {}

        //When the mouse moves, this function is called.
        virtual void mouseMoved(Component *source, KEY_MODIFIERS modifier, MOUSE_BUTTON id, int X, int Y) {}

        //When the mouse is pressed, this function is called.
        virtual void mousePressed(Component *source, KEY_MODIFIERS modifier, MOUSE_BUTTON id, int X, int Y) {}

        //When the mouse is released, this function is called.
        virtual void mouseReleased(Component *source, KEY_MODIFIERS modifier, MOUSE_BUTTON id, int X, int Y) {}

        //When the mouse is clicked, this function is called.
        virtual void mouseClicked(Component *source, KEY_MODIFIERS modifier, MOUSE_BUTTON id, int X, int Y) {}

        //When the mouse enters a component, this function is called.
        virtual void mouseEntered(Component *source, KEY_MODIFIERS modifier, MOUSE_BUTTON id, int X, int Y) {}

        //When the mouse exits a component, this function is called.
        virtual void mouseExited(Component *source, KEY_MODIFIERS modifier, MOUSE_BUTTON id, int X, int Y) {}
};

And then in the form class I did:

LRESULT Form::WinProc(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
        case WM_MOUSEMOVE:
        {
            GetKeyMouseInfo(wParam, mouse, key);

            for (MouseListener* listener : mouse_listeners)
            {
                listener->notify(MOUSE_EVENTS::MOVED, NULL, key, mouse, mouse_x, mouse_y);
            }

            if (!Tracking)
            {
                Tracking = true; …
triumphost 120 Posting Whiz

Here: http://pastie.org/private/c1qqrhycdpa1dk6flgonw

Same code you have but working. Only 1 line changed. Your error was because WM_CREATE is called before the default statement. If you initialise inst before you enter the switch statement, it will work.

cambalinho commented: thank you very much +2
triumphost 120 Posting Whiz

I couldn't understand the question.

Yes you could use it for child controls. Store the HWND or ID of the child control as well as the pointer to it in a map. Whenever an event is triggered, look up the ID or HWND and return the pointer to the control with that ID or HWND.

For me, the easier option is actually subclassing the control. If you do this, each control has its own WindowProc. Whenever an event is triggered, it'd just trigger its event listener.

Other than that, I couldn't figure out what you were trying to ask.

triumphost 120 Posting Whiz

@Cambalinho: What you did wrong was to not make the changes I told you to make earlier. Might have missed it by accident.

You needed to have: if (inst->Create != NULL).. You should be testing your function pointers for NULL before calling them. That was the reason for your access violation.

The next thing is that you didn't put the inst = (form* )GetWindowLongPtr(...); in the case statement.

Other than that, I didn't change anything else.

cambalinho commented: thanks for all... really thanks +0
triumphost 120 Posting Whiz

Here is your code.. I modified it to work.. The window will show for 5 seconds and then disappear.

http://pastie.org/private/8aspaldrbai204h8yvpew

And these are the changes made: http://www.diffchecker.com/lm9l4m3y

cambalinho commented: thank you very much +0
triumphost 120 Posting Whiz

Hmm.. well you must be doing something different.. The code I ran actually works. I tested everything before posting it.

Here is the project I tested:

Project Link

It includes Listeners and stuff similar to Java's.

There is already an example in the above project-link.

If you don't want to use that code then you will have to post everything you have because there really isn't enough information for me to tell you what is wrong with the code you currently have.

triumphost 120 Posting Whiz

Ok but did you try what I said in the previous post? That fixes your error.

triumphost 120 Posting Whiz

Your code is wrong.. How can you NOT get errors? There is no way that code would have compiled without the above fixes.. And to fix your runtime errors you need to change the code to the following:

    static LRESULT CALLBACK WndProcForm(HWND HandleWindow, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        static POINT PreviousLocation, Location;
        static bool Tracking = false;
        static MouseButtons MBButtons;
        static bool blControl=false;
        static bool blShift=false;
        static bool blResize=false;
        static int xPos=0;
        static int yPos=0;
        static UINT_PTR timerid;
        static bool blnDrag=false;

        //you're missing the below line..
        form *inst = (form *)GetWindowLongPtr(HandleWindow, GWLP_USERDATA);


         HBRUSH g_hbrBackground = NULL;

        //Working with messages
        switch(msg)
        {
            case WM_NCCREATE:
            {
                CREATESTRUCT *p = (CREATESTRUCT *)lParam;
                inst = (form *)p->lpCreateParams;
                SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)form);
                inst->hwnd = hwnd;
            }
            break;

            case WM_CREATE:
            {
                if(WindowMain==NULL)
                    WindowMain=HandleWindow;

                if (inst->Create != NULL) //you're also missing this line!
                    inst->Create(inst->intLeft, inst->intTop);
            }
            break;

            //..
            //..
            //..
        }
    }

You are also missing the main part of WinAPI windows:

while(GetMessage(Hwnd, 0, 0, 0, 0) > 0) do
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
triumphost 120 Posting Whiz

@Cambalinho..

Your errors were:

case WM_NCCREATE:
{
    CREATESTRUCT *p = (CREATESTRUCT *)lParam;
    inst = (form *)p->lpCreateParams;

    SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)form); //error.. hwnd should be: HandleWindow parameter.  (LONG_PTR)form should be: (LONG_PTR)inst..
    //The line above should be: SetWindowLongPtr(HandleWindow, GWLP_USERDATA, (LONG_PTR)inst);

    inst->hwnd = hwnd; //should be: inst->hwnd = HandleWindow;
    if (inst == NULL)
        inst = (form *)GetWindowLongPtr(hwnd, GWLP_USERDATA); //error.. hwnd should be: HandleWindow parameter.
        //The line above should be: (form *)GetWindowLongPtr(HandleWindow, GWLP_USERDATA);
}
break;

If you fix it, it should look like:

case WM_NCCREATE:
{
    CREATESTRUCT *p = (CREATESTRUCT *)lParam;
    inst = (form *)p->lpCreateParams;
    SetWindowLongPtr(HandleWindow, GWLP_USERDATA, (LONG_PTR)inst);
    inst->hwnd = HandleWindow;

    if (inst == NULL)
        inst = (form *)GetWindowLongPtr(HandleWindow, GWLP_USERDATA);
}
break;

Also, I'd like you to read here: http://www.daniweb.com/software-development/cpp/threads/423106/separate-headers-from-source

I also like coding your way before.. I switched to the proper way and got so used to it. Please read the above for proper coding ethics. It will help you improve too. It helped me.

cambalinho commented: thanks +0
triumphost 120 Posting Whiz

The code I gave you works out of the box. I cannot tell what your error is without line numbers and context.

That setParent is not a member function so how are you passing this as the last argument to CreateWindowEx?

As far as I can tell, the only thing you did use the NCCreate. If you don't explain exactly what those functions are above, and why they aren't member functions, there isn't much I can do.. The example I gave you was to use member functions. Otherwise you're going to have to explicitly pass the instance pointer to CreateWindowEx.

Also, that is a LOT of static variables.

triumphost 120 Posting Whiz

Bad code here?

SetProp(hwnd, formpropname, (HANDLE)FormClass.lpfnWndProc);

hwnd = CreateWindowEx(0, classname, "The title of my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, parent, NULL, mod, (LPVOID) this);

HWND isn't assigned when you call SetProp. You probably want to create the window before calling SetProp.

The real way to implement what you're looking for is as follows:

#include <windows.h>


/** 
  BaseForm abstract class.
  All other forms/windows must inherit from this one.
**/
class BaseForm
{
    private:
        HWND m_Hwnd;

    public:
        BaseForm() : m_Hwnd(NULL) {}
        ~BaseForm() {m_Hwnd = NULL;}

        bool Create(const char *Title, POINT Location, unsigned short Width, unsigned short Height, HWND Parent);

    protected:
        virtual int Show();
        HWND GetHWND() const {return m_Hwnd;}
        static LRESULT __stdcall WindowProcedure(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam);
        virtual LRESULT WinProc(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam) = 0;
};

int BaseForm::Show()
{
    MSG Messages = {0};
    ShowWindow(m_Hwnd, SW_SHOW);

    while(GetMessage(&Messages, nullptr, 0, 0))
    {
        TranslateMessage(&Messages);
        DispatchMessage(&Messages);
    }
    return Messages.wParam;
}

bool BaseForm::Create(const char *Title, POINT Location, unsigned short Width, unsigned short Height, HWND Parent)
{
    WNDCLASSEX FormClass;
    FormClass.cbSize        = sizeof(WNDCLASSEX);
    FormClass.style         = 0;
    FormClass.lpfnWndProc   = WindowProcedure;
    FormClass.cbClsExtra    = 0;
    FormClass.cbWndExtra    = 0;
    FormClass.hInstance     = GetModuleHandle(NULL);
    FormClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    FormClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    FormClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    FormClass.lpszMenuName  = NULL;
    FormClass.lpszClassName = "BASE_FORM";
    FormClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassEx(&FormClass);
    m_Hwnd = CreateWindowEx(0, "BASE_FORM", Title, WS_OVERLAPPEDWINDOW, Location.x, Location.y, Width, Height, Parent, NULL, GetModuleHandle(NULL), this);
    return m_Hwnd != NULL;
}

LRESULT __stdcall BaseForm::WindowProcedure(HWND Hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    BaseForm *frm = NULL;

    if (Msg == WM_NCCREATE)
    { …
cambalinho commented: thanks +2
triumphost 120 Posting Whiz

This will work. You MUST have visual styles enabled in order to have an icon AND text at the same time..

Of course, you do not want to use the "EnableVisualStyles" function below. Do it with a manifest and a resource file! It is much better.. The below is simply to show you WHY it works.

#include <commctrl.h>

void EnableVisualStyles()
{
    char sys_dir[MAX_PATH] = {0};
    DWORD len = GetSystemDirectory(sys_dir, sizeof(sys_dir) / sizeof(sys_dir[0]));
    if (len < sizeof(sys_dir) / sizeof(sys_dir[0]))
    {
        ACTCTX actCtx =
        {
            sizeof(ACTCTX), ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_SET_PROCESS_DEFAULT |
            ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID, "shell32.dll", 0, 0, sys_dir, reinterpret_cast<char*>(0x7C)
        };

        ULONG_PTR ulpActivationCookie = false;
        ActivateActCtx(CreateActCtx(&actCtx), &ulpActivationCookie);
    }
}

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HWND HandleButton;
    static HICON HandleIcon;

    switch (message)
    {
        case WM_DESTROY:
            DestroyIcon(HandleIcon);
            PostQuitMessage(0);
            break;

        case WM_CREATE:
            EnableVisualStyles();

            HandleButton = CreateWindow(
                               "BUTTON",
                               "Test",
                               WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
                               0, 0,
                               300, 100,
                               hwnd,
                               (HMENU)1,
                               NULL,
                               NULL
                               );
            HandleIcon=(HICON)LoadImage(NULL,"c:/acrobat.ico",IMAGE_ICON,LR_DEFAULTSIZE,LR_DEFAULTSIZE,LR_LOADFROMFILE);
            SendMessage(HandleButton,BM_SETIMAGE,(WPARAM)IMAGE_ICON,(LPARAM)HandleIcon);
            break;

        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}
cambalinho commented: THANK YOU VERY MUCH +2
triumphost 120 Posting Whiz

While I look over the code, I just have one comment before I post something useful.. I really hope you can change 1 thing.. DO NOT #include .cpp files. It is a bad habit and will get you in a lot of trouble down the line.

I must also ask, is this a snippet from a book? It has a copyright which is why I asked. Is it for your company or just a snippet from a book you want help on.

Looking at your code, it is very hard to tell what you are doing. What I see is:

You removing from the queue by calling ppq.remove which I assume returns a boolean according to your declaration.

What you should be doing is:

while(!queue.isEmpty())
{
    data = ppq.peek();
    //print the data here..
    ppq.remove();
}

This peek is required because you have no pop and remove returns a boolean rather than the item from the queue. peek + remove will return an item and remove from the queue.

triumphost 120 Posting Whiz

See: ScrollWindowEx

The above ScrollWindowEx is exactly what you need to use. When you draw on the DC, draw on the entire DC. The entire width and height of your image.

When you want to clip a specific part to the client area, you may scroll it or set a clipping region. The clipping region will define the area that is drawn.

It can be done with a Bitblt/StretchBlt as well by specifying the drawing area.

triumphost 120 Posting Whiz

You need to link to GDI32

triumphost 120 Posting Whiz

You could do what microsoft does in WinAPI.

Call once to get the length required. The second call to the function will use a buffer with that length.

C functions also do this. One example is mbstowcs. This way the user allocates their own memory and knows that they must clean it up.

Example:

int strapp(const char* str_one, const char* str_two, char* result)
{
    int size_one = 0;
    int size_two = 0;

    while(str_one[size_one++]);
    while(str_two[size_two++]);  
    int total_size = size_one + size_two;

    if (!result) return total_size;

    int i = 0, j = 0;
    while(str_one[i]) result[i] = str_one[i++]; 
    while(str_two[j]) result[i++] = str_two[j++];

    result[i] = '\0';
    return total_size;
}

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int size = strapp("hello", " world", NULL);
    char* str = malloc(size + 1);

    strapp("hello", " world", str);
    printf("%s", str);

    free(str);
}

It is annoying having to calculate length of both strings twice though.. So I guess your solution really might be the best there is..

triumphost 120 Posting Whiz

Don't mean to grave dig a 2 day old thread but are you sure:

const char *strapp(const char *str, const char *s)
{
    string ret="";
    ret+=str;
    ret+=s;
    return ret.c_str();
}

is valid? I ask because I'm wondering what will happen to the returned result when ret (its owner) gets destroyed. I think it might be undefined behaviour.