Advertisement

Pen is ambiguous

Started by February 09, 2023 10:40 AM
9 comments, last by NightCreature83 1 year, 10 months ago

I am running a small test of gdiplus. I have this code:

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

using namespace Gdiplus;
using namespace std;

int main()
{
   GdiplusStartupInput gdiplusStartupInput;
   ULONG_PTR gdiplusToken;
   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

   // Create a window
   HWND hWnd = CreateWindow(L"STATIC", L"My Window", WS_OVERLAPPEDWINDOW,
       100, 100, 500, 500, NULL, NULL, NULL, NULL);
   ShowWindow(hWnd, SW_SHOW);

   // Create a device context
   HDC hdc = GetDC(hWnd);

   // Create a GDI+ graphics object
   Graphics graphics(hdc);

   // Draw a line
   Pen pen(Color(255, 0, 0, 255));
   graphics.DrawLine(&pen, 10, 10, 200, 200);

   // Clean up
   ReleaseDC(hWnd, hdc);
   GdiplusShutdown(gdiplusToken);
   return 0;
}

However, it is complaining the Pen is ambiguous. Can anyone help me see the two or more places where Pen is declared?

Thank you.

pen doesn't seem to be a variable?
You're using pen as a static function, which I'm guessing it's not…

From examples I see you should do either of these:
Pen pn1 = new Pen(blueBrush, 3);
Pen pn1 = Pens.Red;

Advertisement

Its most likely the compiler telling you it cant figure out which constructor you are meaning to call where you create your pen. Can you provide the actual compile error.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

m_waddams said:
pen doesn't seem to be a variable? You're using pen as a static function, which I'm guessing it's not…

It's a direct initialization: https://en.cppreference.com/w/cpp/language/direct_initialization

ms75214 said:
Pen pen(Color(255, 0, 0, 255));

However, it is complaining the Pen is ambiguous.

Read your error carefully. At a guess, it is the error “Call of overloaded constructor is ambiguous”. Almost certainly the error is that it cannot decide which constructor to use The GDIPlus Pen class has four constructors, and what you have written is very close to (but not quite a match of) the constructor with a default width parameter: Pen::Pen(const Color&,REAL)

Add the second parameter for the pen width, such as 1.0f and the ambiguity should be resolved. That is, Pen pen(Color(255, 0, 0, 255), 1.0f); to create a one-pixel wide pen.

Also, for some reason, I get this error when debugging it:

Exception thrown at 0x00007FFF11E362BA (GdiPlus.dll) in gditest.exe: 0xC0000005: Access violation writing location 0x000001EBBBB22308.

I don't know why this happens. Anyone know?

Thanks.

Advertisement

You're trying to write in some space that isn't owned by the application (the OS says “no” to the application). This typically happens when data structures aren't setup properly, eg a pointer is not initialized and points at a random address or the call that you make assumes things you didn't provide.

C++ assumes you know what you're doing. It doesn't believe in hand-holding. It does what you tell it to do even if you try shooting yourself in your foot. There are no safe guards built-in. As a result you must be careful in deciding the next step. (On the positive side, this “the user knows what should be done” philosophy allows you to organize things exactly as you like, eg for maximum performance. That's what C++ excels in.)

If you look at the code, you are making calls to libraries etc, and you don't do any form of checking if the call actually worked. In your current code. If a call fails for some reason, then you currently try to use the result of a failed call, which generally leads to some kind of disaster.

So check with the documentation that you meet the requirements before you make a call, and afterwards check in the code that a call succeeded, even (or perhaps, especially!) in simple test code. It costs you a few minutes, but will save you hours to weeks in hunting weird bugs.

@Alberth It looked like it didn't like the destructors of the GDI+ objects being called after GdiplusShutdown.

I changed the code, and that access violation is gone:

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

using namespace Gdiplus;
using namespace std;

int main()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

// Create a window
HWND hWnd = CreateWindow(L"STATIC", L"My Window", WS_OVERLAPPEDWINDOW,
 100, 100, 500, 500, NULL, NULL, NULL, NULL);
ShowWindow(hWnd, SW_SHOW);

// Create a device context
HDC hdc = GetDC(hWnd);

{
 // Create a GDI+ graphics object
 Graphics graphics(hdc);

 // Draw a line
 Pen pen(Color(255, 0, 0, 255));
 graphics.DrawLine(&pen, 10, 10, 200, 200);
}
// Clean up
ReleaseDC(hWnd, hdc);
GdiplusShutdown(gdiplusToken);

return 0;
}

Unfortunately, now the window just disappears.

ms75214 said:

Unfortunately, now the window just disappears.

Well the program ends so unless I'm missing something, that's what I'd expect.

Add a message loop to your application so your window doesnt instantly end because it exits main.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

This topic is closed to new replies.

Advertisement