I'm using Visual Studio Community 2019 Version 16.10.4. I've created a Win32 C++ app that displays a bmp picture. I've been trying to embed the picture into the complied .exe but not having success. My goal is to create the .exe without the need for any additional files or folders.
I did the following:
Right click on the App name in the Solution Explorer
Select Add from the dropdown and New Item from the popup box
Select Resource in the left column and Resource File(.rc) in the right column, then the Add button at the bottom
A pop up occurred: warning RC4005: '_APS_NEXT_RESOURCE_VALUE':redefinition, select OK
In the Resource View, right click on Resource.rc and select Add Resource… at the bottom
Select Bitmap and select New
There were a few more steps, but I lost track after trying to resolve the issue.
In the Solution Explorer under Resource Files I have Resource.rc and art1.bmp. For art1.bmp I have it so it is not excluded from the build. A resource.h file was also created.
resource.h has the following:
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Resource.rc
//
#define IDB_BITMAP1 103
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
In the .rc file, it has the following (and more)
IDB_BITMAP1 BITMAP "art1.bmp"
I have art1.bmp in the project root, Release folder and Debug folder.
After I compile the code into Release x86, the picture shows up without any issues (same in Debug) when I run the .exe. If I delete the picture from the Release folder, the picture no longer shows up.
Any suggestions on what step or steps I missed or what I need to change so the picture will be part of the .exe and not a seperate file?
A big thank you to Igor, With his help, this issue is finally resolved.
My original code (which was not posted at the time) was:
bitmap = (HBITMAP)LoadImageA(NULL, "art1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
Igor correctly asked "do you use IDB_BITMAP1 anywhere in your code?" which it was not.
I manage to get farther, but it still failed:
bitmap = (HBITMAP)LoadImageA(NULL, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
I had tried replacing LR_LOADFROMFILE with NULL without success. The final key Igor provided was GetModuleHandle(nullptr) and NULL for UINT.
bitmap = (HBITMAP)LoadImageA(GetModuleHandleA(nullptr), MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0, NULL);
Related
In a Rust desktop application, some version of the window struct is always used, e.g., WNDCLASSW. When WNDCLASSW is defined, a class icon may be added through the struct member hIcon. The code excerpt below demonstrates how to include the icon stored in the file Icon.ico.
...
let hicon: HICON = LoadImageW(
0 as HINSTANCE,
wide_null("Icon.ico").as_ptr(),
IMAGE_ICON, 0, 0, LR_LOADFROMFILE
) as HICON;
let hinstance = GetModuleHandleW(null_mut());
let mut wc: WNDCLASSW = std::mem::zeroed();
wc.lpfnWndProc = Some(window_proc);
wc. hInstance = hinstance;
wc.hIcon = hicon;
wc.lpszClassName = name.as_ptr();
...
The icon file is loaded during the program execution and must be stored in the same folder as the exe file. If the icon file is missing, LoadImageW() returns a NULL handle. Setting hIcon to NULL is valid and causes the use of a standard system icon.
While this approach produces the required icon, the icon file is loaded during execution and must be delivered along with the exe file. This isn't an acceptable solution; the icon should be linked to the exe file and delivered within it.
How do I link an icon to a Rust Windows application and use it there?
I am aware of this solution, but it generates thousands of lines of errors and warnings during compilation and must be seen as outdated. This solution works, but it only adds the exe icon shown in Windows File Explorer, while the class icon (in the taskbar) is unchanged. Several other solutions for the exe icon may be found on the internet, but this is not what I'm looking for.
The standard procedure to embed resources into an executable image on Windows is to author a resource file (.rc), have the resource compiler translate that into its binary representation, and pass that to the linker.
Since it's somewhat tedious to interact with the linker from Cargo, it's a fair bit easier to use an existing crate to deal with this. As you've discovered, there's winres (which appears to be a bit outdated), so I'll be using embed-resource here.
If you want to play along, start by creating a new binary crate
cargo new --bin embed_icon
Next, copy an icon of your choosing into the crate's root directory (I'm using "rust_lang_logo.ico" downloaded from here) and create the resource script (embed_icon.rc) in the same location:
1 ICON "rust_lang_logo.ico"
All this does is tell the resource compiler that it should look for an icon called "rust_lang_logo.ico", and assign it an ID of 1 when producing its binary output.
Of course we need a Cargo.toml as well:
[package]
name = "embed_icon"
version = "0.0.0"
edition = "2021"
[dependencies.windows]
version = "0.43.0"
features = [
"Win32_Foundation",
"Win32_UI_WindowsAndMessaging",
"Win32_System_LibraryLoader",
]
[build-dependencies]
embed-resource = "1.8"
This is declaring the required windows features we'll be using, and imports embed-resource as a build dependency. What's left is src/main.rs
use windows::{
core::{Result, PCWSTR},
Win32::{
System::LibraryLoader::GetModuleHandleW,
UI::WindowsAndMessaging::{LoadImageW, IMAGE_ICON, LR_DEFAULTSIZE},
},
};
fn main() -> Result<()> {
let _icon = unsafe {
LoadImageW(
GetModuleHandleW(None)?,
PCWSTR(1 as _), // Value must match the `nameID` in the .rc script
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE,
)
}?;
Ok(())
}
This doesn't do much, other than trying to load the icon we just embedded into the binary. A cargo run later, and we have...
Error: Error { code: HRESULT(0x80070714), message: "The specified image file did not contain a resource section." }
and a binary that looks like this in File Explorer:
The final step is to actually run embed-resource and have the icon linked into the executable image. A build script is required to do this. To add one create a file called "build.rs" in the crate's root directory with the following contents:
fn main() {
embed_resource::compile("embed_icon.rc");
}
This neatly brings it all together. Running the executable is now successful, and the binary has a nice icon associated with it when displayed in File Explorer:
Note: The solution above uses the windows crate, which is designed for convenience and better safety. If you are using the winapi or windows-sys crate the core principles are still the same. The code in main.rs would have to be adjusted, though.
This text complements Answer 1 by IInspectable, adding information for the users of winapi.
Create the resource file <name>.rc and build.rs as described in Answer 1, and place these files along with the icon file <name>.ico in the project root directory. Add the build dependency to embed-resource in Cargo.toml. The application exe file built with these changes will embed the icon from the icon file.
To change the class icon that is shown in the taskbar, set the hIcon member in WNDCLASSW as follows:
hIcon = LoadImageW(
GetModuleHandleW(0 as LPCWSTR), // hInst; the .exe file
MAKEINTRESOURCEW( 1 ), // name; use the resource number in the .rc file
IMAGE_ICON, // type
0, // cx
0, // cy
0 // fuLoad
) as HICON;
I'm c++ programmer. I can make message box with my icon with .ico file extension. I can make with MSGBOXPARAMS. My question is, if got answers, to make MessageBox with my icon with .bmp file extension. Too make in MSGBOXPARAMS?
Try with resource, create macro andnBITMAPvalue is of bitmap for MessageBoxIcon.
Sample:
head1.h
#define RCICON 23
res1.rc
#define RCICON 23
RCION BITMAP "example.bmp"
And try, MSGBOXPARAMS member for icon is example macro RCICON.
I have a simple Win32 project generated by VS 2012. In the resource.h file, I saw this:
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
I found it is been referenced in a couple places in the resource.rc file. But I could not understand what it means. Neither did I find reference about it online. Any idea?
When creating child controls by calling CreateWindowEx, you have to assign a control ID (through the overloaded hMenu parameter). The control ID can later be used to refer to a control, without having to store the dynamically created HWND (e.g. when calling GetDlgItem or GetDlgItemInt).
Some controls rarely need to be identified in code. A prominent example is the Static Control1, that, if defined in a resource script, usually does not need to be referenced in code. You (or the dialog manager) still need to pass a control ID when creating the control, even though you don't use it later on. For those controls you can pass the IDC_STATIC control ID, that is defined in a wizard-generated Resource.h file2.
1 Other examples include the Icon Control (a static control with the SS_ICON style), the Line Control (a static control with the SS_ETCHEDHORZ and SS_SUNKEN styles), or the GroupBox Control.
2 This is not a convention of the Windows API3. It is strictly a decision made by user code. You could use another ID value, or not define IDC_STATIC at all if you want, and use an integer literal in the LTEXT control statement instead: LTEXT "Filename", -1, 10, 10, 100, 100
3 Granted, the SDK header winres.h does define the preprocessor symbol IDC_STATIC as (-1), so if you do define it in your code, make sure to assign the same value to avoid any confusion.
I met this problem. I have a simple Win32 program which is like the boilerplate which I can get from selecting a "Win32 project" under Visual Studio 2010's "Template --> Visual C++".
I found all other Windows based program like Adobe Reader, Windows Explorer having the feature which is: you enlarging the main window to a new size and then select "Close" or "Exit" from File menu or system menu to close it, then you launch the program again, the main window would be of the size that you adjusted to last time. However that program I got from Visual Studio as the bootstrap does not have such feature.
I researched more on it but cannot find which setting in either WndClass or CreateWindow that I can tweak to make that happen. Does anyone know it, thank you for your help in advance.
The simplest way to do this is with the GetWindowPlacement() and SetWindowPlacement() functions. These manage the window size and state (minimized/maximized/restored) for you.
Call GetWindowPlacement() when you want to record your window's current state:
WINDOWPLACEMENT wp = {0};
wp.length = sizeof(wp);
if (GetWindowPlacement(hWnd, &wp))
{
// save wp values somewhere...
}
You can then save the values of the WINDOWPLACEMENT structure somewhere in your program's configuration files - either in the registry or on disk.
To restore your window's information, load the saved values into the WINDOWPLACEMENT structure, then call the SetWindowPlacement() function:
if (values were previously saved)
{
WINDOWPLACEMENT wp = {0};
wp.length = sizeof(wp);
// load wp values from somewhere...
SetWindowPlacement(hWnd, &wp);
}
You will need to save the position (X, Y) and size (Height, Width) of the window yourself, and set those values when the program starts up again.
Depending on the nature of the program, you might set this in a configuration file, a registry key, or a database (among other options).
I'm working on a Windows app that needs to run on XP, Vista, 7, and 8. I'm trying to set the application icon, and it works, using DI_ICON1 as the tag in my RC file:
DI_ICON1 ICON DISCARDABLE "myapp.ico"
Using IDI_ICON1 didn't seem to do the right thing here.
However, I also create a second window (also at the root level, ie not a child of my app's main window) and the ALT-TAB icon for that second window wasn't showing up correctly; it was just the default, generic app icon. Adding a second line to the RC now made the ALT-TAB icon work:
IDI_ICON1 ICON DISCARDABLE "myapp.ico"
so with both lines everything works. But I don't know why or how or wtf these identifiers even mean. So what are they, where are they defined, and by what magic do they work?
IDI_ICON1 is just a unique name identifying the resource. You can give it any name as long as it is unique. The development environment should generate a Resource.h file that uses a #define preprocessor directive to assign it a 16-bit unsigned integer unique identifier.
See:
https://learn.microsoft.com/en-us/windows/win32/menurc/icon-resource
https://learn.microsoft.com/en-us/cpp/windows/resource-files-visual-studio?view=msvc-170
IDI_ICON1 is probably just a convention that someone came up with, where IDI means "ID Icon", and 1 is because it is the first icon being defined. So, if you were defining another icon you'd identify it with IDI_ICON2. If you were defining a bitmap resource, you would identify it with IDB_BITMAP1.
DISCARDEABLE is only relevant for 16-bit Windows. See: https://learn.microsoft.com/en-us/windows/win32/menurc/common-resource-attributes