【问题标题】:How to get address of function return value inside constructor via pointer如何通过指针在构造函数中获取函数返回值的地址
【发布时间】:2016-09-28 18:16:49
【问题描述】:

我试图在构造函数中访问函数的返回值地址。我有一个指向类构造函数的指针,但是无论我尝试什么组合都会给我一个错误。通过这个例子,我认为我走上了正确的道路:

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

我了解指针的工作原理,阅读了很多关于它的内容,我确信这纯粹是关于语法的。我在上面的示例中遇到了错误编译器错误 C2276,所以我看了一下here,但是当我尝试推荐的内容时,它也不起作用:

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

现在错误是:

错误 C2664 'Gdiplus::Status Gdiplus::Graphics::DrawLine(const Gdiplus::Pen ,const Gdiplus::Point &,const Gdiplus::Point &)':无法从 'Gdiplus 转换参数 1 ::Pen (__thiscall CustomButton:: )(void)' to 'const Gdiplus::Pen *'

首先它不应该是无效的,因为它被声明了(我认为),其次将它声明为 const 也无济于事。但我看到我走在正确的轨道上,因为编译器不再抱怨无效的语法。

在研究过程中,我查看了herehere(这里他们的建议与 MSDN 相同)、herehere(我尝试了所有可能的括号组合但收效甚微)和更多页面而且我无法比这更进一步(我也尝试使用'*',但这对我来说毫无意义,因为我不想再做一个指针)。

我是 C++ 新手,在这个问题上花了两个多小时。我试图尽可能清楚地描述问题;如果我在发布此类问题时做错了什么,请告诉我,我会在下一篇文章中避免它。

完整代码:

#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);
}

标题:

#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

【问题讨论】:

    标签: c++ winapi gdi+


    【解决方案1】:

    你的构造函数有这个:

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

    这会在堆栈上创建 frontBrush 和 frontPen,然后立即销毁它们,因为它们的 范围 仅限于构造函数。它们需要是成员变量(如widthheight等),并且可以在构造函数的前导中构造:

    CustomButton::CustomButton()
       : frontBrush(Gdiplus::Color(255, 160, 160, 160))
       , frontPen(&frontBrush, 1)
    {
    .
    .
    .
    }
    

    【讨论】:

    • 我尝试了这个解决方案,但没有成功,我遇到了更多错误。我在标题中声明了与宽度和高度相同的方式,我将它添加到原始帖子中,也许还有问题?谢谢你帮助我阿拉斯泰尔!
    • 我在一段时间后通过更改标题修复了这些问题(我在声明中留下括号,就好像它是函数一样,删除那些有帮助的)。我还将 graphics.DrawPath(&frontPen, &gfxPath) 更改为 graphics.DrawPath(&(CustomButton::frontPen), &gfxPath) 解决了这些行的所有错误,但在 CustomButtonProc 中的错误与原始帖子中的错误保持一致。跨度>
    • 错误有:C2664 'Gdiplus::Status Gdiplus::Graphics::DrawLine(const Gdiplus::Pen ,const Gdiplus::Point &,const Gdiplus::Point &)' : 无法将参数 1 从 'const Gdiplus::Pen CustomButton:: ' 转换为 'const Gdiplus::Pen *'
    • 在您的所有电话中尝试graphics.DrawLine(&amp;p_CustomButton-&gt;frontPengraphics.DrawLine
    • @DanielMaczak:不赞成票的可能原因:文字过多(问题中有很多不相关的文字);缺少minimal reproducible example(发布的代码肯定不是最少的);问题实际上是要求非常基础(如何访问班级成员);没有为您的编译器使用适当的警告级别(在 /W4 它会告诉您,您没有访问/初始化类成员)。
    猜你喜欢
    • 2021-11-17
    • 1970-01-01
    • 2015-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多