Reputation: 2633
I am trying to embed an icon in my WIN32 GUI application to use as the background for a button using Visual Studio. I am able to add the resource without a problem and can view it in the 'Resource View' tab. When I compile and run my program, I get no errors and I can run the EXE fine, however the icon that is displayed over my button seems to be one of Windows' default icons.
The default identifier for my icon when I add it to visual studio is 102. I have tried changing this to other numbers but still end up with the wrong icon being displayed on the button. The strange thing is that using the same reference to the icon resource, I can set the application icons just fine
From the "WinUser.h" file: (those are my comments):
#define IDI_APPLICATION MAKEINTRESOURCE(32512) // Shows when my iconid=100
#define IDI_HAND MAKEINTRESOURCE(32513) // " " = 101
#define IDI_QUESTION MAKEINTRESOURCE(32514) // " " = 102
#define IDI_EXCLAMATION MAKEINTRESOURCE(32515) // " " = 103
#define IDI_ASTERISK MAKEINTRESOURCE(32516) // " " = 104
#define IDI_WINLOGO MAKEINTRESOURCE(32517) // " " = 105
#define IDI_SHIELD MAKEINTRESOURCE(32518) // " " = 106
If I change the identifier to be outside of this range, the LoadImage function fails and no icon is loaded. I can't explain this and have no idea how to proceed.
My resource.h file:
#define IDI_ICON1 102
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
My resource.rc file (generated by Visual Studio.. I removed the comments):
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "winres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#ifdef APSTUDIO_INVOKED
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
IDI_ICON1 ICON "angery.ico"
#endif
My source file:
// main.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c
#include "resource.h"
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <CommCtrl.h>
#include <ShlObj.h>
#include <ShlObj_core.h>
#include <stdio.h>
HINSTANCE hInstMain;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
// Define and set parameters for the windows class attribute
WNDCLASSEX wcex;
HWND hWnd;
MSG msg;
hInstMain = hInstance; // Adding this line solved my problem.
// ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstMain;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("Dummy");
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON1));
if (!RegisterClassEx(&wcex)) {
MessageBox(NULL, _T("Failed"), _T("Failed"), MB_OK);
return -1;
}
hWnd = CreateWindow(_T("Dummy"), _T("Example"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
100, 100, NULL, NULL, hInstMain, NULL);
if (!hWnd) {
MessageBox(NULL, _T("AHH"), _T("AHH"), MB_OK);
return -1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
HDC hdc;
HWND myButton;
HICON myIcon;
switch (message) {
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_CREATE:
myButton = CreateWindow(_T("Button"), NULL, WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON | WS_TABSTOP | BS_ICON,
10, 10, 50, 50, hWnd, NULL, NULL, NULL);
//myIcon = (HICON)LoadImage(hInstMain, _T("angery.ico"), IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
myIcon = (HICON)LoadImage(hInstMain, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
if (!myIcon) {
MessageBox(NULL, _T("Icon fail"), _T("Icon fail"), MB_OK);
return -1;
}
SendMessage(myButton, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)myIcon);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
An icon, for your convenience (depicting my mood towards VS right now). https://drive.google.com/file/d/1HoPInZukIvAVkWs38l3MnfUkQ7HpLktR/view?usp=sharing I don't think the icon is corrupt because I've tried it with several icons from several different sources.
I would like to be able to load my own icon into a button while having it embedded in the exe so I don't have to send the image around as well.
Upvotes: 0
Views: 844
Reputation: 4016
You do not set hInstMain
. If it is zero, LoadImage loads OEM images. Also, why create controls on WM_PAINT?
Upvotes: 2