Remove an already created DrawTextA inside a hooked application - c++

I've been working on a DLL hook for a game that allows to modify some in game memory things to greater my knowledge in hooking and modifying memory etc. I've come to a point where i can't quite figure out how to continue!
I've created a font and displayed it to the screen using the below method..
LPD3DXFONT g_pFont = NULL;
HRESULT WINAPI hkEndScene(LPDIRECT3DDEVICE9 pDevice)
{
if(g_pFont == NULL){
D3DXCreateFontA(pDevice, 12, 0, FW_BOLD, 1, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Verdana", &g_pFont);
}
if(g_pFont != NULL)
{
RECT rect = { 10, 10, 500,200 };
g_pFont->DrawTextA(NULL, "Text to draw to screen", -1, &rect, 0,tGreen);
}
return oEndScene(pDevice);
}
Now what i need to figure out is how I can remove that DrawTextA from the screen, or change it's text to something else. I have absolutely no clue how to do this!
Any help is greatly appreciated, thanks all!

Well, it looks like I didn't quite understand how EndScene worked! Looks like it's drawn at the end of every frame and I just need to do an if statement to get it to go away!
if(g_pFont != NULL)
{
//RECT struct - left,top,right,bottom in pixels
if(g_timer < 2000){
RECT rect = { 10, 10, 500,200 };
g_pFont->DrawTextA(NULL, "Draw this and remove this", -1, &rect, 0,tGreen);
}
}
g_timer is set to ++ inside of the hkDrawIndexedPrimitive thread.

Related

Capturing a specific window using BitBlt return the black or transparent border which represent the classic gui layer

I tried to capture a screenshot of specific window using BitBlt and save it to clipboard, but it returns the screenshot with the content inside window border only while the window border itself is remain transparent or blacked out with many weird behaviors.
The expected result should be the full window border with the full content:
This is the actual result:
This is what I tried:
Comment the SetLayeredWindowAttributes function before performing BitBlt but the result is the entire black screenshot.
Tried to set the delay after UpdateWindow function but the weird border remains the same.
Disabling some coded option but it didn't help...
Use PrintWindow but the result is the classic gui border, which is not the intended goal (and many article indicate about the problem with this function).
I don't have any idea why this happened nor able to find out due to lack of information of this command when searching Internet.
Is there anything wrong with my code?
void QuickScreenshot()
{
HWND windowHandle(::FindWindowW(0, L"Internet Download Manager 6.41"));
ANIMATIONINFO AnimationInfo{};
SystemParametersInfoW(SPI_GETANIMATION, sizeof(ANIMATIONINFO), &AnimationInfo, NULL);
auto DefaultAnimationInfo(AnimationInfo);
AnimationInfo.iMinAnimate = 0;
DefaultAnimationInfo.cbSize = sizeof(ANIMATIONINFO);
SystemParametersInfoW(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &AnimationInfo, WM_SETTINGCHANGE);
auto originalExstyle(GetWindowLongW(windowHandle, GWL_EXSTYLE));
SetWindowLongW(windowHandle, GWL_EXSTYLE, WS_EX_LAYERED);
COLORREF windowColor;
BYTE windowAlpha, customAlpha(1);
DWORD flag;
WINDOWPLACEMENT windowState{};
windowState.length = sizeof(WINDOWPLACEMENT);
GetLayeredWindowAttributes(windowHandle, &windowColor, &windowAlpha, &flag);
SetLayeredWindowAttributes(windowHandle, windowColor, customAlpha, flag);
GetWindowPlacement(windowHandle, &windowState);
if (windowState.showCmd == SW_SHOWMINIMIZED)
{
if ((windowState.flags & WPF_RESTORETOMAXIMIZED) == WPF_RESTORETOMAXIMIZED)
{
ShowWindow(windowHandle, SW_MAXIMIZE);
}
else
{
ShowWindow(windowHandle, SW_SHOWNORMAL);
}
}
else
{
ShowWindow(windowHandle, windowState.showCmd);
}
RECT windowRectangleCoordinates;
GetWindowRect(windowHandle, &windowRectangleCoordinates);
InvalidateRect(windowHandle, &windowRectangleCoordinates, TRUE);
UpdateWindow(windowHandle);
Sleep(100);
HDC ScreenContentHandle(GetWindowDC(windowHandle));
HDC DestinationContentHandle(CreateCompatibleDC(ScreenContentHandle));
auto cx(windowRectangleCoordinates.right - windowRectangleCoordinates.left);
auto cy(windowRectangleCoordinates.bottom - windowRectangleCoordinates.top);
HBITMAP BitmapHandle(CreateCompatibleBitmap(ScreenContentHandle, cx, cy));
HGDIOBJ oldObject(SelectObject(DestinationContentHandle, BitmapHandle));
//PrintWindow(windowHandle, ScreenContentHandle, NULL);
BitBlt
(
DestinationContentHandle,
0, 0, cx, cy,
ScreenContentHandle,
0, 0,
SRCCOPY | CAPTUREBLT
);
SaveToClipboard(BitmapHandle);
SelectObject(DestinationContentHandle, oldObject);
DeleteDC(DestinationContentHandle));
ReleaseDC(NULL, ScreenContentHandle));
DeleteObject(BitmapHandle));
ShowWindow(windowHandle, SW_MINIMIZE);
SetLayeredWindowAttributes(windowHandle, windowColor, windowAlpha, flag);
SetWindowLongW(windowHandle, GWL_EXSTYLE, originalExstyle);
SystemParametersInfoW(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &DefaultAnimationInfo, WM_SETTINGCHANGE);
}

Resize cursor is showing on the border of a fixed dialog frame

It is a bit difficult to provide you with a minimal working example here but I am going to try and explain this issue that I have only just noticed.
The Context
So, I have a regular CDialogEx derived class, defined like this:
class CChristianLifeMinistryStudentsDlg : public CDialogEx
I have set it up so that the borders will not resize:
The main application (also CDialogEx based) has a fixed window. That behaves correct.
From the menu the user displays a resizable dialogue (an editor).
On this dialog is a button the user can press which will in turn display the popup modal dialog I am referring to.
What Happens
When this dialog is displayed I have noticed this when you hover the mouse over the dialog borders:
I don't understand why this is happening.
Cursor Management
In the "editor" that spawns this popup window I do have some cursor management like this:
BOOL CChristianLifeMinistryEditorDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (CPersistentWaitCursor::WaitCursorShown())
{
RestoreWaitCursor();
return TRUE;
}
return CDialogEx::OnSetCursor(pWnd, nHitTest, message);
}
But, I have tried temporarily to invoke this popup from my main application dialog which does not have an cursor management and the result is still the same.
Spy Results
As requested I have just used Spy to examine the window styles:
As anticipated we suddenly have WS_THICKFRAME set, when it was not in the resource editor!
So
In my RC file the dialog has the DS_MODALFRAME flag set but at runtime it ends up having the WS_THICKFRAME set. As far as I am aware I never make these changes for these affected dialog objects.
Update
I have found out the following:
BOOL CChristianLifeMinistryStudentsDlg::OnInitDialog()
{
LONG_PTR lStyle = GetWindowLongPtr(GetSafeHwnd(), GWL_STYLE);
if (lStyle & WS_THICKFRAME)
AfxMessageBox(_T("Thick"));
else if (lStyle & DS_MODALFRAME)
AfxMessageBox(_T("Modal"));
CDialogEx::OnInitDialog();
If I put the check code before the CDialogEx::OnInitDialog(); call the style is set as DS_MODALFRAME. But if I put the same check code after the CDialogEx::OnInitDialog(); call it is then changed to WS_THICKFRAME. Why?
OK
So, the CDialogEx::OnInitDialog method calls CWnd::LoadDynamicLayoutResource(LPCTSTR lpszResourceName). This in turn calls CWnd::InitDynamicLayout(). And in that method it does this:
if (!bIsChild && (pDialog != NULL || pPropSheet != NULL))
{
CRect rect;
GetClientRect(&rect);
ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);
::AdjustWindowRectEx(&rect, GetStyle(), ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle());
SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOOWNERZORDER);
}
There we go. So it is because I am using CDialogEx as my base class. Is this a bug in MFC?
Clarification
The "Editor" (parent window of the popup that owns the button) does use dynamic layout functonality:
But in this instance the popup does not need to. But it is because my popup is derived from CDialogEx that this is happening.
The plot thickens
So this is the MFC code that is always called with CDialog::OnInitDialog:
BOOL CWnd::LoadDynamicLayoutResource(LPCTSTR lpszResourceName)
{
if (GetSafeHwnd() == NULL || !::IsWindow(GetSafeHwnd()) || lpszResourceName == NULL)
{
return FALSE;
}
// find resource handle
DWORD dwSize = 0;
LPVOID lpResource = NULL;
HGLOBAL hResource = NULL;
if (lpszResourceName != NULL)
{
HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_DIALOG_LAYOUT);
HRSRC hDlgLayout = ::FindResource(hInst, lpszResourceName, RT_DIALOG_LAYOUT);
if (hDlgLayout != NULL)
{
// load it
dwSize = SizeofResource(hInst, hDlgLayout);
hResource = LoadResource(hInst, hDlgLayout);
if (hResource == NULL)
return FALSE;
// lock it
lpResource = LockResource(hResource);
ASSERT(lpResource != NULL);
}
}
// Use lpResource
BOOL bResult = CMFCDynamicLayout::LoadResource(this, lpResource, dwSize);
// cleanup
if (lpResource != NULL && hResource != NULL)
{
UnlockResource(hResource);
FreeResource(hResource);
}
if (bResult)
{
InitDynamicLayout();
}
return bResult;
}
For some reason this call BOOL bResult = CMFCDynamicLayout::LoadResource(this, lpResource, dwSize); is return TRUE. As a result the dialog eventually calls InitDynamicLayout. In my other dialogs that are popups this does not happen. Instead, bResult ends up as FALSE and thus the frame is not resized.
So why does it think it worked?
Worked it out. I don't remember doing this but for some reason some of my controls on the dialog had dynamic properties set. For example:
I had to set all of these properties back to None. Then it behaved.
You can easily tell if a given dialog resource has any dynamic properties by opening your resource file in a text editor. For example:
IDD_DIALOG_OUR_CHRISTIAN_LIFE_AND_MINISTRY_MATERIAL AFX_DIALOG_LAYOUT
BEGIN
0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 10, 0,
0, 0, 0, 0,
50, 0, 0, 0,
50, 0, 0, 0,
0, 0, 0, 0,
0, 0, 10, 0,
0, 0, 0, 0,
50, 0, 0, 0,
50, 0, 0, 0,
0, 0, 0, 0,
0, 0, 10, 0,
0, 0, 0, 0,
50, 0, 0, 0,
50, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
END
If something like the above is present then your dialog will be deemed as having a dynamic layout, and thus the settings for the dialog are modified:
ModifyStyle(DS_MODALFRAME, WS_POPUP | WS_THICKFRAME);
The resource will look like this when it has no dynamic control properties:
IDD_DIALOG_OUR_CHRISTIAN_LIFE_AND_MINISTRY_MATERIAL AFX_DIALOG_LAYOUT
BEGIN
0
END
I chose to manually reset each control via the IDE. However, I guess you could modify the text file manually.
As to why I had controls with dynamic properties in the first place, well, I can't tell you. I might have been fiddling in the past with the dialog and not realised the side effect to the border frame. Or, possibly, I may have copied controls from one resource on to another and it carried the dyanmic values.
The interesing side note is that whilst the MFC code set the border as thick, it did not change it sufficiently to enable dialog resizing. But that is another matter!
At least we now know the cause of the issue and how to easily identify the dialogs in the resource that have dynamic layouts.

ShowCursor(FALSE) does not hide cursor on console application

I know this may sound to be a duplicate question but trust me it's not.
I have referred this question, but was not of much help as I am trying with a console application and the answerer himself tells he does not know the reason why ShowCursor(FALSE) does not work for console applications.
This thread did not help me either.
Here are the things I tried:
Using ShowCursor():
while(ShowCursor(false)>=0); //did not work
I first suspected that it was because of this statement in the msdn :
When Windows starts up, it checks if you have a mouse. If so, then the cursor show count is initialized to zero; otherwise, it is initialized to negative one.
I thought maybe in the latest windows, it doesn't recognize the connected mouse or the trackpad as an installed mouse and maybe that's why it didn't work. The following code shows it is not the case:
void UsingShowCursor()
{
CURSORINFO info;
info.cbSize = sizeof(CURSORINFO);
cout << ShowCursor(FALSE);
cout << ShowCursor(FALSE);
cout << ShowCursor(FALSE);
GetCursorInfo( &info ); //info.flags is CURSOR_SHOWING
}
Because I get -1, -2, -3. That means the initial show cursor count is obviously 0 and it does identify the installed mouse.
And another thing to note is that the GetCursorInfo() also tells that the cursor is showing.
Using SetCursor()
void UsingSetCursor()
{
HCURSOR prev = SetCursor(NULL);
int i = 0;
while(i++<10)
{
cout<<i<<endl;
Sleep(1000);
}
if( SetCursor(prev) == NULL ) //check if the previos cursor was NULL
cout<<"cursor was hidden and shown after 10 secs\n";
}
Doesn't work either.
This also did not work:
SetCursor(LoadCursor(NULL, NULL));
Edit:
Using LoadImage
Did not work either.
void UsingLoadImage()
{
// Save a copy of the default cursor
HANDLE arrowHandle = LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED);
HCURSOR hcArrow = CopyCursor(arrowHandle);
HCURSOR noCursorHandle = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR,1,1,LR_SHARED); //a single pixel thick cursor so that it wont be visible
HCURSOR noCursor = CopyCursor(noCursorHandle);
SetSystemCursor(noCursor, OCR_NORMAL);
int i =0 ;
while(i++<10)
{
cout<<i<<endl;
Sleep(1000);
}
//revert to previous cursor
SetSystemCursor(hcArrow, OCR_NORMAL);
DestroyCursor(hcArrow);
}
What can be the mistake? How can we hide the mouse for a console application?
You can use LoadImage() to achieve what you want. Here is the modified working version of the function UsingLoadImage() you quoted in the question. You have to include a cursor resource file to your visual studio project. Download the cursor from here or create your own.
Resource Files->Add->Existng Item and browse to the nocursor.cur file.
void UsingLoadImage()
{
// Save a copy of the default cursor
HANDLE arrowHandle = LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED);
HCURSOR hcArrow = CopyCursor(arrowHandle);
// Set the cursor to a transparent one to emulate no cursor
HANDLE noCursorHandle = LoadImage(GetModuleHandle(NULL), L"nocursor.cur", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE); //worked
//HANDLE noCursorHandle = LoadCursorFromFile(L"nocursor.cur"); //this also worked
HCURSOR noCursor = CopyCursor(noCursorHandle);
SetSystemCursor(noCursor, OCR_NORMAL);
int i =0 ;
while(i++<10)
{
cout<<i<<endl;
Sleep(1000);
}
SetSystemCursor(hcArrow, OCR_NORMAL);
DestroyCursor(hcArrow);
}
This would replace the normal arrow cursor with the transparent one. If you want to hide all the other cursor like the text, loading, hand cursors etc you have to hide them individually. If you don't want that to be the case, then you should opt out of the console application as many commenters have pointed out.
Hope this helps.

C++ GDI+ Objects Memory leak/too many objects?

ive been making a c++ drawing program and i have a part where im drawing using gdi+ inside a function so i need to declare my graphics object every time i call the function.. this obviously is wrong and causes a leak somewhere so after some calls it gets slower and then suddenly stops drawing all together ,as expected.
im trying to clear my objects every time it finishes drawing but it doesnt seem to solve the issue. i thought maybe the PEN objects are part of the issue but some insight would be very helpful
my code:
void function()
{
DWORD pdwGduStartup;
GdiplusStartupInput GdiStartupInp;
GdiplusStartup(&pdwGduStartup, &GdiStartupInp, NULL);
Pen pnPen_Blue(Gdiplus::Color(255, 0, 0, 255), 2.0F);
Pen pnPen_Green(Gdiplus::Color(255, 255, 0, 255), 2.0F);
LPCSTR LGameWindow = "MyWindow";
HWND hGameWindow = FindWindow(NULL, LGameWindow);
Graphics graphics(GetDC(hGameWindow));
for (int n=10; n>0; n--)
graphics.DrawLine(&pnPen_Green,0, 0, 0, n);
GdiplusShutdown(pdwGduStartup);
graphics.Flush();
}
thanks alot!
edit: added release DC did not do anything!
DWORD pdwGduStartup;
GdiplusStartupInput GdiStartupInp;
GdiplusStartup(&pdwGduStartup, &GdiStartupInp, NULL);
Pen pnPen_Blue(Gdiplus::Color(255, 0, 0, 255), 2.0F);
Pen pnPen_Green(Gdiplus::Color(255, 255, 0, 255), 2.0F);
LPCSTR LGameWindow = "MyWindow";
HWND hGameWindow = FindWindow(NULL, LGameWindow);
HDC GDC = GetDC(hGameWindow);
Graphics graphics(GDC);
ReleaseDC(hGameWindow, GDC);
GdiplusShutdown(pdwGduStartup);
graphics.Flush();
My GDI objects still rises up to 10,000!
GdiplusShutdown must be called after all GDI+ objects are removed. In your code Pen and Graphics destructors are called after GdiplusShutdown, when the objects go out of scope.
I guess the problem is in GetDC. You should call ReleaseDC or use WTL smart pointers.
As I remember such things where easy to debug with task manager. It shows HANDLE count as well as GDI object count for a process, so you can see what lines generate new objects.
I didnt code my GDI+ right logically. in the logic first you need to create the graphics object, and only then loop draw on it. anything else is WRONG and code wont fix it!
Try something like this, use pointers that you can easily delete when done.
DWORD pdwGduStartup;
GdiplusStartupInput GdiStartupInp;
GdiplusStartup(&pdwGduStartup, &GdiStartupInp, NULL);
Pen pnPen_Blue* = new Pen(Gdiplus::Color(255, 0, 0, 255), 2.0F);
Pen pnPen_Green* = new Pen(Gdiplus::Color(255, 255, 0, 255), 2.0F);
LPCSTR LGameWindow = "MyWindow";
HWND hGameWindow = FindWindow(NULL, LGameWindow);
HDC GDC = GetDC(hGameWindow);
Graphics* g = new Graphics(GDC);
// Do stuff here
ReleaseDC(hGameWindow, GDC);
delete pnPen_Blue;
delete pnPen_Green;
g->Flush();
delete g;
delete GDC; // not sure
GdiplusShutdown(pdwGduStartup);

How to clear drawing area for ActiveX OCX control?

I have some trouble drawing an ActiveX control. In the screenshot below you see the control after a resize in the VB6 IDE. The control's outline from before the resize is still shown on the left-hand side of the control:
Here is the code that draws a black ellipsis with a red Z:
void CzFileIoXCtrl::OnDraw(CDC* pdc,
const CRect& rcBounds,
const CRect& rcInvalid)
{
if (!pdc)
{
return;
}
pdc->SetBkMode(TRANSPARENT);
pdc->SelectObject(CBrush::FromHandle((HBRUSH)GetStockObject(BLACK_BRUSH)));
pdc->Ellipse(rcBounds.left, rcBounds.top,
rcBounds.left + rcBounds.Width(),
rcBounds.top + rcBounds.Height());
HFONT font = CreateFont(int(rcBounds.Height() * 0.7),
int(rcBounds.Width() * 0.5),
0, 0, FW_BLACK, FALSE, FALSE, FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY,
FF_DECORATIVE, NULL);
pdc->SelectObject(font);
pdc->SetTextColor(RGB(255, 0, 0));
DRAWTEXTPARAMS params = { sizeof(DRAWTEXTPARAMS), 1, 0, 0, 1 };
RECT bounds = rcBounds;
CString z(L"Z");
pdc->DrawTextEx(z, &bounds, DT_CENTER | DT_VCENTER | DT_SINGLELINE, &params);
}
How can I clear the drawing area?
I managed to reproduce this in the vb form editor. It looks like the problem comes because you do not draw anything outside the ellipse. So, you can draw a rectangle in the entire area like this before drawing anything in OnDraw().
pdc->FillRect( rcBounds, &CBrush(TranslateColor( AmbientBackColor() )) );
I tested this and is working fine.