I have an object, dc, of type CDC and I'd like to get an HDC object.
I read the MSDN documentation here, but don't really understand it.
Can someone provide me with a brief example/explanation on how to do this?
When you have CDC object it will be implicitly converted to HDC when necessary:
CDC dc;
HDC hdc = dc; // HDC hdc = dc.operator HDC();
If you have pointer to CDC object then using function GetSafeHdc will look more clear:
CDC* pdc = SOME;
HDC hdc = pdc->GetSafeHdc();
CDC class has operator HDC() defined which allows the compiler to convert a CDC object to HDC implicitly. Hence if you have CDC* and a function which takes HDC then you just dereference the pointer and send it to the function.
CDC is a C++ class which - to a reasonable approximation - encapsulates an HDC, which is a handle to a device context.
The documenation which you link to describes a conversion operator, which is a C++ construct that classes can supply to allow implicit conversion from an instance of a class to some other type. In this case the implicit conversion results in the underlying handle (HDC) which the CDC instance encapsulates.
You can perform the conversion by using a CDC instance anywhere were it needs to be converted to an HDC.
Most simply:
void f( const CDC& cdc )
{
HDC hdc = cdc;
// use hdc here
}
HDC hDC = dc;
Just assign it.
CDC cdc = something.
HDC hdc = cdc;
if (hdc != 0)
{
//success...
}
Related
I am creating some functions that facilitate a little bit GDI+. I have created this function to begin paint to be used in WM_PAINT:
Graphics StartPaint(HWND win, HDC *hdc, PAINTSTRUCT *ps)
{
*hdc = BeginPaint(win, ps);
Graphics g(*hdc);
return g;
}
It gives compile error and takes me to "gdiplusgraphics.h" and points to
this line:
Graphics(const Graphics&);
saying that it is private.
After several tries I discovered that the problem is with the return statement in the function. Why does the return statement give such an error, and how can I solve this problem?
I use codeblocks.
Thank you.
Thank you all. The function now works well as follows:
Graphics *StartPaint(HWND win, HDC *hdc,
PAINTSTRUCT *ps)
{
*hdc = BeginPaint(win, ps);
return new Graphics(*hdc);
}
Not sure why but im using Deleaker plugin to detect memory leaks.
in my code in debug build its saying i have amemory leak at GetDC
Then in release build it is saying i have a leak at CreateCompatibleDC
are these real leaks or false?
my delete objects are called when my class closes.
HDC hdc = GetDC(_hWnd);
_hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(_hdcMem, _hBitmap);
while (_execute.load(std::memory_order_acquire))
{
func();
BitBlt(hdc, 0, 0, _Width, _Height, _hdcMem, 0, 0, SRCCOPY);
}
SelectObject(_hdcMem, hbmOld);
DeleteDC(_hdcMem);
DeleteObject(hbmOld);
DeleteObject(_hBitmap);
DeleteDC(hdc);
After GetDC, you must call ReleaseDC—not DeleteDC. DeleteDC is only used with CreateCompatibleDC. This is all spelled out in the documentation in case you forget.
Also, you are incorrectly cleaning up your device context. The reason you save the handles to the old objects is so that you can reselect them into the DC. You cannot delete them! Objects that are selected into a device context cannot be deleted—they are in use. (If you were checking the return values of these API functions, you would know that, because they would have returned an error.)
The code should look like this:
HDC hdc = GetDC(_hWnd);
_hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(_hdcMem, _hBitmap);
while (_execute.load(std::memory_order_acquire))
{
func();
BitBlt(hdc, 0, 0, _Width, _Height, _hdcMem, 0, 0, SRCCOPY);
}
SelectObject(_hdcMem, hbmOld);
DeleteObject(_hBitmap);
DeleteDC(_hdcMem);
ReleaseDC(_hWnd, hdc);
It is unclear to me why you are using global variables for _hdcMem and _hBitmap when their scope is limited to this single bit of code. You create them at the top, and destroy them at the bottom, so they are useless outside of this code. You should limit their scope to just this section of the code, too. Being able to reason about the lifetime of objects/variables is key to stomping out memory leaks.
Note that using a library that wraps these native resources up in an RAII fashion (constructor acquires; destructor releases) would be a wonderful idea. It not only frees you from having to remember the details of how to clean up each time, but it also ensures that your code is exception-safe. If func() were to throw here, you would certainly have a memory leak. That is something a really good static analyzer would tell you as well.
You must use ReleaseDC() to free the HDC returned by GetDC().
Do not delete the hbmOld that SelectObject() returned. Just select it back into the HDC and let ReleaseDC() handle its deletion.
virtual BOOL Create(
LPCTSTR lpszCaption,
DWORD dwStyle,
const RECT& rect, //we need to pass a RECT instance
CWnd* pParentWnd,
UINT nID
);
// Create a push button.
myButton1.Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
CRect(10,10,100,30), pParentWnd, 1);
CRect(10,10,100,30) is a constructor,does this mean the constructor return a instance?
//CRect(10,10,100,30) is a constructor...
No it is not. It is the declaration of an object. It does call the constructor but the object is created locally, not returned by the constructor.
This code is equivalent to the following :
CRect rect = CRect(10,10,100,30);
// Create a push button.
myButton1.Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
rect, pParentWnd, 1);
The constructor returns an instance of the class it is constructed, which is used by the Create function.
For this example i am talking about hooking BeginPaint() which i hooked fine and i can normally access everything pre-call...
HDC WINAPI Mine_BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint)
{
// do stuff here, inspecting PRE-CALL lppaint struct etc...
return fpBeginPaint(hWnd, lpPaint);
}
I am looking for a way to inspect this lpPaint struct post-call, how could i do this?
HDC WINAPI Mine_BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint){
// do stuff here, inspecting PRE-CALL lppaint struct etc...
HDC result = fpBeginPaint(hWnd, lpPaint);
//inspect here whatever you want.
return result;
}
I was wondering, do I need to call DeleteObject in the following case?
CFont* oldFont = label.GetFont();
LOGFONT oldLogFont;
oldFont->GetLogFont(&oldLogFont);
oldLogFont.lfWeight = FW_BOLD;
CFont newFont;
newFont.CreateFontIndirectW(&oldLogFont);
label.SetFont(&newFont, true);
// Do I need to call oldFont->DeleteObject() or newFont->DeleteObject()?
Thanks.
No you don't. MFC classes are RAII classes. When the object drops out of scope (ie gets deconstructed) the object will be deleted appropriately.