Win32: Small Icon doesn't show - c

I'm learning Win32 programming
I used LoadImage(...) to set the small icon for the window but it doesn't seem to be working and I cannot pinpoint the problem
void AddIcons(HWND hw)
{
HICON hi = LoadImage(NULL, "ICON.bmp", IMAGE_BITMAP, 16, 16, LR_LOADFROMFILE);
printf("Icon initialized\n");
if(hi)
{
printf("%x\n", hi);
SendMessage(hw, WM_SETICON, ICON_SMALL, (LPARAM)hi);
}
}
And the windows procedure:
LRESULT CALLBACK WndProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_SETICON: printf("REQUEST RECEIVED\n");
}
.
. // AddIcons() is called here
. // DefWindowProc() handles the message at the end
}
I get all three print statements including REQUEST RECEIVED.
However, the icon is still the default. Where is the problem occuring?
I am aware that I can use keep a resource file and use LoadIcon(..) but I am more comfortable doing everything programatically. Which begs a second question:
Can everything that can be done using resource(.rc) files be done programmatically?
If so, is one method inherently better than the other?

Related

In WinAPI, how do I know when the mouse has moved outside the current window?

Basically, I want to write a program that shows in a small window the color of the pixel currently pointed by the mouse cursor.
Of course, I could poll the mouse cursor position once in a while, but I would like to opt to a mechanism that calls my code when the mouse cursor has moved, regardless whether it's pointing the current window or not.
Is there some WinAPI trickery that could achieve that functionality?
After some search, I found this:
HHOOK mouseHook =
SetWindowsHookExA(
WH_MOUSE_LL,
LowLevelMouseProc,
hInstance,
0);
...
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (wParam == WM_MOUSEMOVE) {
// Notify me.
}
return 0;
}

Dont know how to correctly edit this code

Well i am still slightly new in C.
Lets say i have this code:
source.c
#include "logger.c"
int main{
FILE *myfile1;
fileX = fopen("myfile.txt, a+);
SetHook(fileX);
}
and then i have very simple keylogger
logger.c
HHOOK _hook;
KBDLLHOOKSTRUCT kbdStruct;
LRESULT __stdcall HookCallback(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0)
{
if (wParam == WM_KEYDOWN)
{
// PRINT INTO THE FILE
kbdStruct = *((KBDLLHOOKSTRUCT*)lParam);
fprintf(fileX, "%c", kbdStruct.vkCode);
}
}
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
void SetHook(fileX)
{
_hook = SetWindowsHookEx(WH_KEYBOARD_LL, HookCallback, NULL, 0)
}
Basically i want to have separated code like this.
But i think this is wrong i need to pass that "fileX" not to function setHOOK() but to that "LRESULT __stdcall..." and i dont know how to do that.
I will be thankfull for any help.
WH_KEYBOARD_LL is global hook you need place its hook procedure in a DLL separate from
the application installing the hook procedure. (For simple purpose you can put hook procedure in your application and it is also working. But this is not suggested way.)
(SetWindowsHookExA function Using Hooks)
This hook is called in the context of the thread that installed it.
The call is made by sending a message to the thread that installed the
hook. Therefore, the thread that installed the hook must have a
message loop. (In another word, the application need have a window so that it can keep pumping messages.)
(LowLevelKeyboardProc callback function)
For learning purpose of hook, my suggestion is getting started using Visual Studio Windows Desktop Application template (C++).
It is simple to register the keyboard hook and receive message in the hook.
And for writing to a file in the hook producer you can create a named file map so that you don't need to pass a file handle to the hook. You can open this file map using its name and write to the file using this file map. (Creating Named Shared Memory)
static HHOOK hhookKeyPress;
hhookKeyPress = SetWindowsHookEx(
WH_KEYBOARD_LL,
KeyboardHookCallback,
NULL,
0);
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Sharing above information to help you get started and then you can find C programming way later. Hope it helps.

Moving frameless window by dragging it from a portion of client area

As the title says, I would like to move the window only when the user will drag it from a portion of the client area. This will be an imitation of the normal caption bar movement and it's because my form is custom and it doesn't have any title or caption bars. At the moment, I use the code as follows:
...
case WM_NCHITTEST:
return HTCAPTION;
and that works fine for making the user able to move the window no matter where he drags from. I would like to limit this possibility (only the top of the window will allow movement). I haven't tried checking the position of the mouse pressed because I don't know how to do it in the WM_NCHITTEST message.
I use plain Win32 (winapi) C code (no MFC or anything else at the moment) in Visual Studio 2015.
You will run into trouble if you just return HTCAPTION in response to all WM_NCHITTEST messages. You will break things like scrollbars, close buttons, resizing borders, etc. that are all implemented via different HT* values.
You have the right idea, though. You want to make the client area of your window draggable, so you need to trick Windows into thinking that your client area is actually the caption area (which, as you know, is draggable). That code looks like this:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// ...
case WM_NCHITTEST:
{
// Call the default window procedure for default handling.
const LRESULT result = ::DefWindowProc(hWnd, uMsg, wParam, lParam);
// You want to change HTCLIENT into HTCAPTION.
// Everything else should be left alone.
return (result == HTCLIENT) ? HTCAPTION : result;
}
// ...
}
However, based on the image in your question, you appear to want to restrict this to only a certain region of your window. You will need to define exactly what that area is, and then hit-test to see if the user has clicked in that area. Assuming that rcDraggable is a RECT structure that contains the bounds of the red box shown in your image (in screen coordinates), you can use the following code:
static RECT rcDraggable = ...
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// ...
case WM_NCHITTEST:
{
// Call the default window procedure for default handling.
const LRESULT result = ::DefWindowProc(hWnd, uMsg, wParam, lParam);
// Get the location of the mouse click, which is packed into lParam.
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
// You want to change HTCLIENT into HTCAPTION for a certain rectangle, rcDraggable.
// Everything else should be left alone.
if ((result == HTCLIENT) && (PtInRect(&rcDraggable, pt))
{
return HTCAPTION;
}
return result;
}
// ...
}
If you define rcDraggable in terms of client coordinates, you will need to convert it to screen coordinates before doing the hit-testing in response to WM_NCHITTEST. To do that, call the MapWindowPoints function, like so:
RECT rc = rcDraggable;
MapWindowPoints(hWnd, /* a handle to your window */
NULL, /* convert to screen coordinates */
reinterpret_cast<POINT*>(&rc),
(sizeof(RECT) / sizeof(POINT)));
You can call some magic code in WM_LBUTTONDOWN handler, AFAIR this:
ReleaseCapture();
SendMessage(yourWindowHandle, WM_SYSCOMMAND, 0xf012, 0) ;
I used this method a few years ago in Delphi and Windows XP. I think it must be similar for c++. Of course, you can check x and y before doing this.

Where do I add my actual program after I establish a Window using WinMain() and WindowProc()? (C++)

First of all, sorry for my ignorance of the window creation process. Today is actually the first day of my experimenting with it.
I started to code a text based game a few days ago and I have the main menu, and 3 or 4 different functions that control various things with text. I was then advised to look into Windows API and create a window for the program. I have created the window which can be seen here:
#include <Windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PWSTR nCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"WindowClass";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.lpszClassName = CLASS_NAME;
wc.hInstance = hInstance;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx( //This creats a new instance of a window
0,
CLASS_NAME,
L"MyFirstWindow",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
500,
NULL,
NULL,
hInstance,
NULL);
if(hwnd == 0)
return 0;
ShowWindow(hwnd,nCmdShow);
nCmdShow = 1;
MSG msg = { };
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:PostQuitMessage(0); return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd,&ps);
FillRect(hdc,&ps.rcPaint,(HBRUSH)(COLOR_WINDOW+5));
EndPaint(hwnd, &ps);
}return 0;
case WM_CLOSE:
{
if(MessageBox(hwnd,L"Do you want to exit?",L"Exit",MB_OKCANCEL)==IDOK)
DestroyWindow(hwnd);
} return 0;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
This looks a bit messy, but you probably will not need it anyway.
So at this point I have my original program and this program that creates a window. My question is how, or even where, do I put my original program's code so that it can be incorporated into the window.
If you are reading this and thinking I'm a total moron for doing it this way, I'm open to ideas that are a lot simpler than what I'm doing right now.
Your code is the standard boilerplate for creating a window using c and win32 API functions. I recommend that you modify the message pump (it's the while loop in middle calling GetMessage). Instead do this:
Run an infinite loop
Peek a message
If the message is not there, execute your code
Else process messages including the quit message
Here's what the code should look like:
while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//Your game code
}
}
I also want to point, that while learning game programming using C and calling Win32 API is a worthy goal, you might want to look at XNA game studio.
The reason I am recommending it is because it is easier to learn and you can make much more interesting games faster. Here are a few links to get you started if you are interested.
http://joshua-w-wise78.livejournal.com/
http://www.krissteele.net/blogdetails.aspx?id=72
http://www.codeproject.com/KB/game/xna1.aspx
http://msdn.microsoft.com/en-us/library/bb203894.aspx
If your original program was a console app, that read input and printed output, then you will probably want to get input from your window to implement your game.
Instead of looking at it from the perspective of read user input from stdin then generate output to stdout, you have to think of it from the view of window messaging. So you need to process the WM_KEYDOWN messages, you can then use DrawText() to show the user input in your client area, or you could use a c++ RichEdit control. Once you process the WM_KEYDOWN messages you know what the user has pressed and then your program can do it's thing (maybe being triggered to process an accumalated buffer of characters whenever the WM_KEYDOWN key is equal to the enter key?) and write the output to your client area using DrawText() or send WM_KEYDOWN messages to your richedit window using SendMessage().
I think this is what you meant by a text based game, anyway, you just have to start thinking of doing everything by monitoring windows messages. Anything that the user does to your window, Windows will send a message to it to let it know.

How can I simulate key presses to any currently focused window?

I am trying to change the keys my keyboard sends to applications. I've already created a global hook and can prevent the keys I want, but I want to now send a new key in place. Here's my hook proc:
LRESULT __declspec (dllexport) HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
int ret;
if(nCode < 0)
{
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
kbStruct = (KBDLLHOOKSTRUCT*)lParam;
printf("\nCaught [%x]", kbStruct->vkCode);
if(kbStruct->vkCode == VK_OEM_MINUS)
{
printf(" - oem minus!");
keybd_event(VK_DOWN, 72, KEYEVENTF_KEYUP, NULL);
return -1;
}
else if(kbStruct->vkCode == VK_OEM_PLUS)
{
printf(" - oem plus!");
keybd_event(VK_UP, 75, KEYEVENTF_KEYUP, NULL);
return -1;
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
I've tried using SendMessage and PostMessage with GetFocus() and GetForegroudWindow(), but can't figure out how to create the LPARAM for WM_KEYUP or WM_KEYDOWN. I also tried keybd_event(), which does simulate the keys (I know because this hook proc catches the simulated key presses), including 5 or 6 different scan codes, but nothing affects my foreground window.
I am basically trying to turn the zoom bar on my ms3200 into a scroll control, so I may even be sending the wrong keys (UP and DOWN).
Calling keybd_event is correct. If all you're doing is a key up, maybe the window processes the key down message instead. You really need to send a key down followed by a key up:
keybd_event(VK_UP, 75, 0, NULL);
keybd_event(VK_UP, 75, KEYEVENTF_KEYUP, NULL);
Or, better yet, send the key down when the OEM key goes down and a key up when the OEM key goes up. You can tell the down/up state by kbStruct->flags & LLKHF_UP.
You may wish to use SendInput, as keybd_event as has been superseded. The MSDN Magazine article C++ Q&A: Sending Keystrokes to Any App has a useful example.
You might want to try Control-UpArrow and Control-DownArrow instead of Up and Down. However this doesn't seem to work for all applications, and even on application where it does work, it may depend on where the focus is.

Resources