Windows C: LoadBitmap() function is not working - c

I write simple windows c program to display the bitmap at the place where the left mouse button is pressed. At the first time when I click my left mouse button, the bitmap appears. But on the second time on words the bitmap is not getting displayed on the place where I made a left mouse click.
Here is my code.........
LRESULT CALLBACK myHandler(HWND hw, UINT m, UINT mextra, long co_ord)
{
HDC hdc, hmemdc;
PAINTSTRUCT ps;
HBITMAP hbmp;
RECT r;
HGDIOBJ holdbmp;
int x, y;
switch(m)
{
case WM_LBUTTONDOWN:
hdc = BeginPaint(hw,&ps);
hmemdc = CreateCompatibleDC(hdc);
hbmp = LoadBitmap(h, MAKEINTRESOURCE(IDB_BITMAP1));
holdbmp = SelectObject(hmemdc, hbmp);
x = LOWORD(co_ord);
y = HIWORD(co_ord);
BitBlt(hdc, x, y, 190, 220, hmemdc, 0, 0, SRCCOPY);
EndPaint(hw,&ps);
SelectObject(hmemdc, holdbmp);
DeleteObject(hbmp);
DeleteDC(hmemdc);
DeleteDC(hdc);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hw,m,mextra,co_ord);
}
return 0L;
}

The code is wrong about seven different ways from Sunday. Even after the changes you've made in response to WhozCraig's comments, it is still wrong.
For starters, the only place you are allowed to call BeginPaint and EndPaint is in response to a WM_PAINT message. You are trying to call these functions in response to a WM_LBUTTONDOWN message. That cannot work. What you'll want to do is trigger a WM_PAINT message from within your WM_LBUTTONDOWN message handler, which you can do by calling the InvalidateRect() function, passing your window handle and NULL for the rectangle to invalidate (to invalidate your entire window). Then, inside of the WM_PAINT message handler, you can call BeginPaint/EndPaint and do your drawing. If you want the drawing to be different depending on whether the left mouse button is down, you can either set a flag inside of the WM_LBUTTONDOWN message handler and test the value of that flag inside of your WM_PAINT message handler, or you can use something like GetKeyState to determine whether the mouse button is down (VK_LBUTTON).
You are also leaking GDI objects because you are not correctly releasing/destroying them. A bitmap that has been loaded with LoadBitmap needs to be destroyed by calling DeleteObject. (However, loading a bitmap repeatedly inside of a WM_PAINT message handler will lead to poor performance. Instead, prefer to load the bitmap a single time in response to the WM_CREATE message, cache its handle in a global or class-level variable, use it when necessary, and destroy the bitmap via that handle in response to the WM_DESTROY message.)
The LOWORD and HIWORD macros should never be used for extracting cursor coordinates. These are liable to return the wrong result on multiple monitor systems. Instead, you should use GET_X_LPARAM and GET_Y_LPARAM. This is specifically mentioned in the MSDN documentation for the WM_LBUTTONDOWN message. Always read the documentation for things you are unfamiliar with!
Finally, the signature for your window procedure is also completely wrong. I have no idea where you got that signature, but not only do you have non-standard parameter names that obscures the actual meaning of those arguments, but you have the wrong types. A window procedure looks like this:
LRESULT CALLBACK myHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
...
}
It is extremely difficult to learn Windows API programming by just hacking around, especially if you aren't disciplined about reading the MSDN documentation. If you really want to learn it, consider purchasing a book, like Charles Petzold's classic Programming Windows, 5th edition (yes, you need the 5th edition, not a newer edition).

Related

How to detect WM_LBUTTONUP messages while in the non client area of a window?

I am trying to allow a window to be dragged by the client area, and still detect WM_LBUTTONUP messages for processing. I have found two commonly suggested ways to drag the windows (listed below), both relying on using non client related functions, but they are unable to detect WM_LBUTTONUP messages upon release of the left click button.
My attempt at receiving WM_LBUTTONUP messages while being able to drag the screen by the client area is to SetTimer every millisecond on WM_LBUTTONDOWN , and use SetWindowPos to move the window with the cursor, then KillTimer on WM_LBUTTONUP. It works and detects WM_LBUTTONUP messages successfully. However, I do not like this solution as the window seems less smooth as it is being dragged around, as compared to the solutions that I found online.
I wish to have the smoothness from the nonclient based solutions. Is there a way to use them to drag the window, AND also receive WM_LBUTTONUP messages at the same time? Thank you for reading!
Example first Non Client Method found online:
case WM_LBUTTONDOWN:
mouseState = 1;
break;
case WM_LBUTTONUP:
mouseState = 0;
break;
case WM_MOUSEMOVE:
{
if (mouseState)
{
POINT CursPt;
GetCursorPos(&CursPt);
PostMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(CursPt.x, CursPt.y));
//mouseState = 0;
}
}break;
Example second Non Client Method found online:
case WM_NCHITTEST:
{
LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
if (hit == HTCLIENT) hit = HTCAPTION;
return hit;
}
The first "example" is nonsensical, I would not use it.
The second "example" might work, but then you have to realize that if you use this, you will never receive WM_LBUTTONDOWN or WM_LBUTTONUP, you will only receive WM_NCLBUTTONDOWN and WM_NCLBUTTONUP. So, you will have to make do with WM_NCLBUTTONUP, and also pray that nothing else in your window relies on proper client-area mouse events.
Another way of doing it (which, as it turns out, does not produce good results, see discussion in the comments blow,) is to do your own window moving:
start moving on WM_LBUTTONDOWN
stop moving on WM_LBUTTONUP
use SetWindowPos() on each WM_MOUSEMOVE while the mouse button is down.

Click button of other window from other process

I'm new to WinAPI and I already created an empty window. Now I want to make a little hack for the tutorial program of Cheat Engine. I already know, how to change values in the memory of other processes. But as soon as I changed a value in the tutorial program, I'm forced to click a "next" button. So my question is: Is it possible to send a click command to a window of another process? I have a handle of the window, a handle of the process and the process id (if it is not the same).
The only thing I know about the buttons is, that their text is always "next".
Here is a shortened version of my code:
HWND hWnd = FindWindow (NULL, L"Window's title"); // Search startup window
DWORD pid; // Get process id
GetWindowThreadProcessId (hWnd, &pid);
HANDLE hProc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid); // Get access to process
DWORD base = 0x789ABCDE; // Get value of static pointer
ReadProcessMemory (hProc, &base, &base, 4, NULL);
WORD offset = 0xBCDE; // Write to memory
WriteProcessMemory (hProc, (void *)(base + offset), (void *)5000, 4, NULL);
// Send click command (???)
Sorry, if my english and/or some technical terms aren't correct, but I'm new to Win32.
EDIT:
I discovered, that the tutorial forbits every memory access, so my project will never work. In addition, GetLastError(); always returns ERROR_INVALID_PARAMETER when I try to install a second windows procedure for the tutorial program. Do I have to use hProc instead of pid in SetWindowsHookEx (WH_CALLWNDPROC, &fnHook, NULL, pid);?
The simplest way to do this is to use SendMessage() to send an WM_LBUTTONDOWN and then a WM_LBUTTONUP message to the given window, something like
// x, y are the coords
SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
SendMessage(hWnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y));
This may or may not work in your particular case; if the spot that you're trying to click is actually in a child window or a popup you've just "clicked" the wrong window, and a lot of apps rely on other messages.
The more reliable way to do it is to call SetWindowsHookEx(WH_MOUSE, ...), and "play" the mouse messages through the given hook procedure. I haven't done that in a couple of decades so can't really talk about it in detail.

What happens if you release an unclean device context?

Normally, if a program selects an object into a device context, or changes its properties, it should change them back before releasing the device context. What happens if it doesn't?
Let's say I do this:
HDC hdc = GetDC(some_window);
SelectObject(hdc, some_font);
SetTextColor(hdc, 0x123456);
SetBkColor(hdc, 0xFEDCBA);
SetROP2(hdc, R2_XORPEN);
ReleaseDC(some_window, hdc);
and some_window's window class does not have the CS_OWNDC or CS_CLASSDC flag. What happens?
Of the functions you listed, SelectObject is the only one that would cause a problem if the object is not de-selected (by selecting the original object). This would cause the some_font resource to be leaked because the DC would have been holding an open handle on it at the time it was released.
You should be doing this:
HDC hdc = GetDC(some_window);
HGDIOBJ hOldObj = SelectObject(hdc, some_font);
// ...
SelectObject(hdc, hOldObj);
ReleaseDC(some_window, hdc);
Or perhaps this:
HDC hdc = GetDC(some_window);
int nSaved = SaveDC(hdc);
SelectObject(hdc, some_font);
// ...
RestoreDC(nSaved);
ReleaseDC(some_window, hdc);
As MSDN notes :
Each of these functions returns a handle identifying a new object.
After an application retrieves a handle, it must call the
SelectObject function to replace the default object. However, the application should save the handle identifying the default object and
use this handle to replace the new object when it is no longer needed.
When the application finishes drawing with the new object, it must
restore the default object by calling the SelectObject function
and then delete the new object by calling the DeleteObject
function. Failing to delete objects causes serious performance
problems.
The failure to restore the original font object causes a handle leak. The OS will retain the handle to some_font. If this code is executed repeatedly then another handle is leaked every time. You will see the Handles count in Task Manager building up. If this goes on for a long time there will eventually be painting failures that appear as junk.

How to handle Win+Shift+LEft/Right on Win7 with custom WM_GETMINMAXINFO logic?

I have a custom windows implementation in a WPF app that hooks WM_GETMINMAXINFO as follows:
private void MaximiseWithTaskbar(System.IntPtr hwnd, System.IntPtr lParam)
{
MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (monitor != System.IntPtr.Zero)
{
MONITORINFO monitorInfo = new MONITORINFO();
GetMonitorInfo(monitor, monitorInfo);
RECT rcWorkArea = monitorInfo.rcWork;
RECT rcMonitorArea = monitorInfo.rcMonitor;
mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left);
mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top);
mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left);
mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);
mmi.ptMinTrackSize.x = Convert.ToInt16(this.MinWidth * (desktopDpiX / 96));
mmi.ptMinTrackSize.y = Convert.ToInt16(this.MinHeight * (desktopDpiY / 96));
}
Marshal.StructureToPtr(mmi, lParam, true);
}
It all works a treat and it allows me to have a borderless window maximized without having it sit on to of the task bar, which is great, but it really doesn't like being moved between monitors with the new Win7 keyboard shortcuts.
Whenever the app is moved with Win+Shift+Left/Right the WM_GETMINMAXINFO message is received, as I'd expect, but MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) returns the monitor the application has just been moved FROM, rather than the monitor it is moving TO, so if the monitors are of differing resolutions the window end up the wrong size.
I'm not sure if there's something else I can call, other then MonitorFromWindow, or whether there's a "moving monitors" message I can hook prior to WM_GETMINMAXINFO. I'm assuming there is a way to do it because "normal" windows work just fine.
According to the MSDN page the WM_GETMINMAXINFO is sent:
"when the size or position of the window is about to change"
which explains why your call to MonitorFromWindow returns the previous monitor.
How about using the WM_WINDOWPOSCHANGED message? It's sent after every time the window is moved. You can get the HWND from the WINDOWPOS structure and use that in a MonitorFromWindow call to get the monitor. When a subsequent WM_GETMINMAXINFO is sent you can use that as you do now.

Smooth animations using Win32 API - without controlling the message pump

I'm currently trying to integrate some animation drawing code of mine into a third party application, under the form of an external plugin.
This animation code in realtime 3d, based on OpenGL, and is supposed to render as fast as it can, usually at 60 frames per second.
In my base application, where I'm the king of the world, I control the application message pump, so that drawing occurs whenever possible. Like that :
for (;;)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
do
{
if (msg.message == WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
}
draw();
}
Now that I'm no more king in the world, I have to play nice with the application messages, so that it keeps being responsive. To my knowledge, as I'm a plugin, I can't hijack the whole application message pump ; so I tried various things, doing my drawing in WM_PAINT message handler :
Use WM_TIMER, which doesn't work :I don't know in advance which time step I need (often not fixed) and the timing in not accurate.
Call InvalidateRect as soon as I'm done drawing, doesn't work : completely prevents the rest of the application of being responsive and doing its own refreshing.
Create a 'worker' thread, whose only job is to post a user message to the plugin window. This message is posted as soon as the drawing is finished (signaled by an event). The user message handler, in turn, calls InvalidateRect (see there).
So far, my last attempt is the better, and sometimes work fine.
DWORD WINAPI PaintCommandThreadProc(LPVOID lpParameter)
{
Plugin* plugin = static_cast<Plugin*>(lpParameter);
HANDLE updateEvent = plugin->updateEvent();
while (updateEvent == plugin->updateEvent())
{
::WaitForSingleObject(updateEvent, 100);
::Sleep(0);
if (updateEvent == plugin->updateEvent())
{
::PostMessage(plugin->hwnd(), WM_USER+0x10, 0, 0);
}
}
return 0;
}
...
LRESULT CALLBACK PluginWinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
bool processDefault = true;
LRESULT result = 0;
Plugin* plugin = reinterpret_cast<Plugin*>( GetWindowLong(hWnd, GWL_USERDATA) );
switch (msg) {
...
case WM_GL_MESSAGE:
{
::InvalidateRect( hWnd, NULL, FALSE );
processDefault = false;
result = TRUE;
}
break;
case WM_PAINT:
{
draw(hWnd);
::SetEvent( plugin->updateEvent() );
processDefault = false;
result = TRUE;
}
break;
...
}
if (processDefault && plugin && plugin->m_wndOldProc)
result = ::CallWindowProc(plugin->m_wndOldProc, hWnd, msg, wParam, lParam);
return result;
}
On some occasions, the host application still seems to miss messages. The main characteristics of the problem are that I have to press the 'Alt' key for modal dialogs to show up ; and I have to move the mouse to give some processing time to the host application !...
Is there any 'industry standard' solution for this kind of as-often-as-you-can animation repaint problem ?
Each thread has its own message queue, and messages sent to a window arrive in the queue of the thread that created the window. If you create your plugin window yourself, you can create it in a separate thread, and that way you will have complete control over its message pump.
An alternative solution (which imho is better), is to only have OpenGL rendering in a separate thread. All OpenGL calls must occur in the thread that created the OpenGL context. However, you can create a window in one thread (your application main thread), but create the OpenGL context in another thread. That way the original application message pumps stays intact, and in your rendering thread you can loop forever doing rendering (with calls to SwapBuffers to vsync).
The main problem with that second solution is that communication between the plugin WindowProc and the rendering loop must take into account threading (ie. use locks when accessing shared memory). However since the message pump is separate from rendering, it can be simultaneous, and your message handling is as responsive as it can get.

Resources