1

I am trying to access functions's return value address inside constructor. I have a pointer to class constructor, but whatever combination I try it gives me an error. With this example I think I got on the right track:

graphics.DrawLine(&p_CustomButton->frontPen, 1, 1, objWidth - 1, objWidth - 1);

I understand how pointers work, read lot about it and I am sure this is purely about syntax. I got error Compiler Error C2276 with example above, so I took a look here but when I tried whats recommended it is not working either:

graphics.DrawLine(&CustomButton::frontPen, 1, 1, objWidth - 1, objWidth - 1);

Now the error is:

Error C2664 'Gdiplus::Status Gdiplus::Graphics::DrawLine(const Gdiplus::Pen ,const Gdiplus::Point &,const Gdiplus::Point &)': cannot convert argument 1 from 'Gdiplus::Pen (__thiscall CustomButton:: )(void)' to 'const Gdiplus::Pen *'

First of all it should not be void since it is declared (I think), and second declaring it as const is not helping either. But I see that I am on the right track as compiler is no longer complaining about invalid syntax.

During my research I took a look here, here (here they advice the same as MSDN), here, here (I tried all possible combinations with brackets with little success) and many more pages and I could not get further than this (I also tried using '*' but it makes no sense to me as I am not trying to make another pointer).

I am new to C++, and have spent more than 2 hours on this issue. I am trying to describe the problem as clearly as possible; if I do something wrong with posting problem like this please let me know, I will avoid it in my next post.

Full code:

#include <windows.h>
#include <commctrl.h>
#include <winuser.h>
#include <gdiplus.h>
#include <string.h>
#include "CustomButton.h"

CustomButton::CustomButton()
{
    width = 0;
    height = 0;
    type = 0;
    customButton = NULL;

    Gdiplus::SolidBrush frontBrush(Gdiplus::Color(255, 160, 160, 160)); // Create a Brush object.
    Gdiplus::Pen frontPen(&frontBrush, 1);
}

CustomButton::~CustomButton()
{
    if (customButton)
        DestroyWindow(customButton);
}

/*set-get functions*/
HWND CustomButton::getButton()
{
    return customButton;
}

void CustomButton::DrawRoundRect(HDC hdc, int X, int Y, int RectWidth, int RectHeight, int CornerRadius)
{
    Gdiplus::Graphics graphics(hdc);
    graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);

    Gdiplus::GraphicsPath gfxPath;

    gfxPath.AddLine(X + CornerRadius, Y, X + RectWidth - (CornerRadius * 2), Y);
    gfxPath.AddArc(X + RectWidth - (CornerRadius * 2), Y, CornerRadius * 2, CornerRadius * 2, 270, 90);
    gfxPath.AddLine(X + RectWidth, Y + CornerRadius, X + RectWidth, Y + RectHeight - (CornerRadius * 2));
    gfxPath.AddArc(X + RectWidth - (CornerRadius * 2), Y + RectHeight - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 0, 90);
    gfxPath.AddLine(X + RectWidth - (CornerRadius * 2), Y + RectHeight, X + CornerRadius, Y + RectHeight);
    gfxPath.AddArc(X, Y + RectHeight - (CornerRadius * 2), CornerRadius * 2, CornerRadius * 2, 90, 90);
    gfxPath.AddLine(X, Y + RectHeight - (CornerRadius * 2), X, Y + CornerRadius);
    gfxPath.AddArc(X, Y, CornerRadius * 2, CornerRadius * 2, 180, 90);
    gfxPath.CloseFigure();

    graphics.DrawPath(&frontPen, &gfxPath);
    graphics.DrawPath(&frontPen, &gfxPath);
}

CustomButton* CustomButton::CreateCustomButton(HINSTANCE hInstance, HWND hwnd, int pos_x, int pos_y, int width, int height, int type)
{
    CustomButton * p_CustomButton = new CustomButton;

    p_CustomButton->customButton = CreateWindowEx(0, L"BUTTON", L"OK", WS_VISIBLE | WS_CHILD | BS_OWNERDRAW, pos_x, pos_y, width, height, hwnd, (HMENU)1, (HINSTANCE)GetWindowLong(hwnd, GWLP_HINSTANCE), p_CustomButton); //BS_OWNERDRAW allows BN_CLICKED to be registered and specifies that DRAWITEM will create mask for the button
    if (p_CustomButton->customButton == NULL)
    {
        delete p_CustomButton;
        MessageBox(NULL, L"Problem creating the Button.", L"Error", 0);
        return 0;
    }

    p_CustomButton->width = width;
    p_CustomButton->height = height;
    p_CustomButton->type = type;

    if (!SetWindowSubclass(p_CustomButton->customButton, CustomButton::CustomButtonProc, 0, (DWORD_PTR)p_CustomButton))
    {
        delete p_CustomButton;
        MessageBox(NULL, L"Problem subclassing the Button.", L"Error", 0);
        return 0;
    }

    return p_CustomButton;
}

LRESULT CALLBACK CustomButton::CustomButtonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    CustomButton *p_CustomButton = (CustomButton*)dwRefData;
    switch (uMsg)
    {
        case WM_NCDESTROY:
        {
            RemoveWindowSubclass(hwnd, CustomButton::CustomButtonProc, uIdSubclass);
            p_CustomButton->customButton = NULL;
            break;
        }
        case 0x8000: //WM_DRAWITEM
        {
            LPDRAWITEMSTRUCT lpdis = (DRAWITEMSTRUCT*)lParam; //assigning drawing structure to the control
            /* drawing the classic windows button */
            SetBkColor(lpdis->hDC, RGB(18, 18, 18)); //background color for the text, which is assigned to the whole button via ETO_OPAQUE in ExtTextOut
            ExtTextOut( //assigns graphic properties to the control
                lpdis->hDC,
                ((lpdis->rcItem.right - lpdis->rcItem.left)) / 2, //X position of the text inside, calculated as half the width
                ((lpdis->rcItem.bottom - lpdis->rcItem.top)) / 2, //Y
                ETO_OPAQUE, //ETO_OPAQUE = button will have the color from SetBkColor
                &lpdis->rcItem, //pointer to rectangle inside the drawing structure
                0, //text inside button
                0, //length of the text string
                NULL);
            lpdis->CtlType = ODT_BUTTON;
            lpdis->itemAction = ODA_DRAWENTIRE;

            int lineWidth = 2;
            int objWidth = 18;

            p_CustomButton->DrawRoundRect(lpdis->hDC, 0, 0, 18, 18, 2);

            Gdiplus::Graphics graphics(lpdis->hDC);
            graphics.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);

            switch (p_CustomButton->type)
            {
                case 1:
                {
                    graphics.DrawLine(&p_CustomButton->frontPen, 1, 1, objWidth - 1, objWidth - 1);
                    graphics.DrawLine(p_CustomButton->frontPen, 1, objWidth - 1, objWidth - 1, 1);
                    graphics.DrawLine(p_CustomButton->frontPen, 1, 1, objWidth - 1, objWidth - 1);
                    graphics.DrawLine(p_CustomButton->frontPen, 1, objWidth - 1, objWidth - 1, 1);
                    break;
                }
                case 2:
                {
                    graphics.DrawLine(p_CustomButton->frontPen, 0, 3, objWidth, 3);
                    break;
                }
                case 3:
                {
                    graphics.DrawLine(p_CustomButton->frontPen, 0, objWidth - 3, objWidth, objWidth - 3);
                    break;
                }
            }
            break;
        }
        case WM_LBUTTONUP:
        {
            switch (p_CustomButton->type)
            {
                case 1:
                {
                    SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0);
                    break;
                }
                case 2:
                {
                    ShowWindow(GetParent(hwnd), SW_MAXIMIZE);
                    break;
                }
                case 3:
                {
                    ShowWindow(GetParent(hwnd), SW_MINIMIZE);
                    break;
                }
            }
            break;
        }
    }
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}

Header:

#ifndef CUSTOMBUTTON_H
#define CUSTOMBUTTON_H

class CustomButton
{
private:
    int width;
    int height;
    int type;
    HWND customButton;
    const Gdiplus::SolidBrush frontBrush; // Create a Brush object.
    const Gdiplus::Pen frontPen;

    CustomButton();
    void DrawRoundRect(HDC hdc, int X, int Y, int RectWidth, int RectHeight, int CornerRadius);

    static LRESULT CALLBACK CustomButtonProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uint_ptr, DWORD_PTR dwRefData);

public:
    ~CustomButton();

    static CustomButton* CreateCustomButton(HINSTANCE hInst, HWND hwnd, int pos_x, int pos_y, int width, int height, int type);
    HWND getButton();
};

#endif
Community
  • 1
  • 1
Xzsh4s575sf75
  • 83
  • 1
  • 11

1 Answers1

1

Your constructor has this:

Gdiplus::SolidBrush frontBrush(Gdiplus::Color(255, 160, 160, 160)); // Create a Brush object.
Gdiplus::Pen frontPen(&frontBrush, 1);

this creates frontBrush and frontPen on the stack, then promptly destructs them as their scope is limited to the constructor only. They need to be member variables (like width, height, etc) and they can be constructed in the preamble of the constructor:

CustomButton::CustomButton()
   : frontBrush(Gdiplus::Color(255, 160, 160, 160))
   , frontPen(&frontBrush, 1)
{
.
.
.
}
Alastair Brown
  • 1,598
  • 8
  • 12
  • I tried this solution with no luck, I get some more errors. I declared those the same way as width and height in header, I will add it to the original post, maybe there is also a problem? Thank you for helping me Alastair! – Xzsh4s575sf75 May 30 '16 at 21:38
  • I fixed those after a while by changing header (I left brackets in declaration as if it was function, deleting those helped). I also changed graphics.DrawPath(&frontPen, &gfxPath) to graphics.DrawPath(&(CustomButton::frontPen), &gfxPath) which solved all errors on those lines, but in the CustomButtonProc the errors remain the same as in original post. – Xzsh4s575sf75 May 30 '16 at 21:54
  • Errors there are: C2664 'Gdiplus::Status Gdiplus::Graphics::DrawLine(const Gdiplus::Pen *,const Gdiplus::Point &,const Gdiplus::Point &)': cannot convert argument 1 from 'const Gdiplus::Pen CustomButton::* ' to 'const Gdiplus::Pen *' – Xzsh4s575sf75 May 30 '16 at 21:56
  • Try `graphics.DrawLine(&p_CustomButton->frontPen` in *all* your calls `graphics.DrawLine` – Alastair Brown May 30 '16 at 22:03
  • I see, so I had it right but the declaration was wrong. I honestly thank you a lot for your help, time and patience. I have one OT question though - I often receive downvotes for questions like this, is there something I should improve to stop getting those? Thank you once more, I couldn't figure this out on my own. – Xzsh4s575sf75 May 30 '16 at 22:08
  • 3
    @DanielMaczak: Possible reasons for the downvotes: Too much text (there's a lot of unrelated text in the question); missing [mcve] (the code posted certainly isn't minimal); the question is really asking for the very basics (how to access class members); not using an appropriate warning level for your compiler (at /W4 it would have told you, that you aren't accessing/initializing class members). – IInspectable May 31 '16 at 08:18
  • @IInspectable Thank you! I got some comments about not desribing in full scale what I tried and for not showing all related code, thank you for the guidelines! Regarding warning level, I will look for some materials about that. – Xzsh4s575sf75 May 31 '16 at 14:29