FindResource works, LoadBitmap doesn't, LoadImage from disk works - c

I am trying to use LoadBitmap to load an image from a resource file.
I've verified that the resource is linked correctly -- examining the final EXE with a hex editor shows that the bitmap is packed inside the EXE correctly.
I've also verified that the bitmap is valid -- using LoadImage with LR_LOADFROMFILE to load the bitmap from disk at runtime works fine and I see it appear when I add it to a gui element later.
I've verified that the ID that I use to access the resource is valid as well -- the FindResource function finds the resource and SizeofResource prints the exact expected number of bytes for the bitmap.
So I have a valid linked resource, a valid ID, and a loadable bitmap.
However, LoadBitmap returns NULL and so does LoadImage if I load from a resource instead of from disk. GetLastError returns 0.
Any ideas? Am I #defining RT_BITMAP in resource.rc correctly?
Thanks.
resource.h
#define BMP_TEST_ID 2
resource.rc
#include "resource.h" // defines BMP_TEST_ID
#define RT_BITMAP 2
BMP_TEST_ID RT_BITMAP "TEST24.BMP"
test.c
#include <windows.h> // defines RT_BITMAP as MAKEINTRESOURCE(2)
#include "resource.h" // defines BMP_TEST_ID
HINSTANCE instance = GetModuleHandle(NULL);
if (!instance) { /* handle error */ }
/* find a bitmap resource with the ID we want -- OK! */
HRSRC rsc = FindResource(instance, RT_BITMAP, MAKEINTRESOURCE(BMP_TEST_ID));
if (!rsc) { /* handle error */ }
/* prints the exact size of the found resource -- GIVES CORRECT OUTPUT */
printf("SizeofResource: %d\n", (int) SizeofResource(instance, rsc));
// ***** THIS BIT DOESN'T WORK *****
/* load bitmap resource -- FAIL! */
HBITMAP bitmap = (HBITMAP)LoadBitmap(instance, MAKEINTRESOURCE(BMP_TEST_ID));
if (!bitmap) { /* handle error */ }
/* load bitmap from file -- OK! */
HBITMAP bitmap2 = (HBITMAP)LoadImage (NULL, "TEST24.BMP", IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if (!bitmap2) { /* handle error */ }
My compiler is amd64-mingw32msvc-gcc 4.6.3

First, you should not have to define RT_BITMAP at all. It is already defined through winuser.h to be included in your c/cpp files. And it turns out you don't need it in your resource file anyway.
The BITMAP resource type will properly assign the right resource type id for your bitmap file. Change your bitmap resource declaration to be:
BMP_TEST_ID BITMAP "TEST24.BMP"
And you should be good to go.

Related

How to figure out the shell's drag/drop icon size for use with SHDoDragDrop?

How do I figure out the right icon size to use so that the icon matches Explorer's default drag-and-drop icon?
(I'm trying to use it with SHDoDragDrop if that matters.)
The size depends on what's in the data object format. From the Shell, it's 96x96.
You can check that if you drag & drop a file into any valid drop target, the data object will contain the "DragImageBits" format and its data is a SHDRAGIMAGE structure:
typedef struct SHDRAGIMAGE {
SIZE sizeDragImage; // will contain 96x96 when dragged from the Shell
POINT ptOffset;
HBITMAP hbmpDragImage;
COLORREF crColorKey;
} SHDRAGIMAGE, *LPSHDRAGIMAGE;
If you're looking for a more static way, here is a code that seems to work, using the UxThemes API. Note that although it uses documented APIs and defines, I don't think it's documented as such.
...
#include <uxtheme.h>
#include <vsstyle.h>
#include <vssym32.h>
...
// note: error checking ommited
auto theme = OpenThemeData(NULL, VSCLASS_DRAGDROP);
SIZE size = {};
GetThemePartSize(theme, NULL, DD_IMAGEBG, 0, NULL, THEMESIZE::TS_DRAW, &size);
MARGINS margins = {};
GetThemeMargins(theme, NULL, DD_IMAGEBG, 0, TMT_CONTENTMARGINS, NULL, &margins);
// final size
size.cx -= margins.cxLeftWidth + margins.cxRightWidth;
size.cy -= margins.cyTopHeight + margins.cyBottomHeight;
CloseThemeData(theme);
As for DPI settings, I understand you want to mimic Explorer, in this case you'll have to do some computation by yourself depending on your needs and screen context, as the image size extracted by the Shell is itself fixed.

winapi create shortcut failed

I want to create shortcut of a file. I found this Microsoft page that describe how to write this, and I copy that in my code to use.
But I have some problems, first it had the following error: "CoInitialize has not been called." I add this CoInitialize(nullptr); to solve the error, but I have error yet.
when I debug it, it has "Information not available, no symbols loaded for windows.storage.dll" error on this line:
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
and after execution when I see the destination path, it creates a shortcut with the name but i can't open it, and it hasn't any content.
What wrong with this?
Does the error make this problem?
I'm using VS 2012.
Code Edited:
// #include "stdafx.h"
#include "windows.h"
#include "shobjidl.h"
#include <iostream>
#include <shlwapi.h>
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"
HRESULT CreateLink(LPCWSTR, LPCWSTR, LPCWSTR);
void wmain(int argc, wchar_t* argv[ ], wchar_t* envp[ ])
{
WCHAR lpwSource[MAX_PATH] = {0};
lstrcpyW(lpwSource, (LPCWSTR)argv[1]);
WCHAR lpwDest[MAX_PATH] = {0};
lstrcpyW(lpwDest, (LPCWSTR)argv[2]);
HRESULT hResult = 0;
hResult = CreateLink(lpwSource, lpwDest, NULL);
if (hResult == S_OK) {
printf("Shortcut was created successfully.\n");
} else {
printf("Shortcut creation failed.\n");
}
getchar();
}
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink, LPCWSTR lpszDesc)
{
HRESULT hres = 0;
IShellLink* psl;
HRESULT hCoInit = 0;
hCoInit = CoInitialize(nullptr);
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres)) {
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres)) {
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(lpszPathLink, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
As I specified in my comment, I've built the code (previous version (Question VERSION #2.) from the one at answer time - which BTW was containing some string conversions that would have most likely failed on non English locales) with VStudio 2013 and ran it on my Win 10 (English) machine. It created a valid shortcut.
So, there was nothing wrong with the code (in the sense that it wouldn't work). The problem was that the output file was also having the .png extension, and when opening it, Win would attempt to use the default image viewer / editor, which would treat the file as PNG (based on its extension). That is obviously wrong, as .lnk files have their own format (as I briefly explained in [SO]: What is the internal structure of a Windows shortcut? (#CristiFati's answer)).
The solution was to properly name the shortcut (let it have the .lnk extension).
Some additional (non critical) notes about the code (current state):
No need for C++ (11) features (nullptr (also check next bullet)):
HRESULT hCoInit = CoInitialize(NULL);
Reorganize the #includes. Use the following list:
#include <windows.h>
#include <shobjidl.h>
#include <shlguid.h>
#include <stdio.h>

How to create shortcut with Win32 API and c language

I want to write a program to create a shortcut for a specific file by using win32 API in c. my IDE is visual studio 2010.
I found this page but its sample just not compile and return many errors.
I also find this code but this always create a link with Target: "D:\Desktop\㩣睜湩潤獷湜瑯灥摡攮數" and I don't know why.
can someone tell me why the sample code of Microsoft is not working or the second one return something in Chinese shape language and also with wrong and constant location for any argument?
This is my code for MSDN sample:
#include "stdafx.h"
#include "windows.h"
#include "winnls.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"
void _tmain(int argc, TCHAR *argv[])
{
CreateLink(argv[1],__argv[2],argv[3]);
}
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc)
{
HRESULT hres;
IShellLink* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
WCHAR wsz[MAX_PATH];
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
// Add code here to check return value from MultiByteWideChar
// for success.
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(wsz, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
and the errors are:
1 error C1083: Cannot open include file: 'stdafx.h' and
2 IntelliSense: cannot open source file "stdafx.h"
CreateLink(argv[1],__argv[2],argv[3]);
This call looks weird. You are using argv[] for two LPCWSTR (const wchar_t *) parameters, but are using __argv[] for an LPCSTR (const char *) parameter. You should change the 2nd parameter to LPCWSTR to match the other parameters, and then use argv[] instead of __argv[].
The TCHAR-based IShellLink works with LP(C)WSTR string parameters, and LP(C)TSTR is LP(C)WSTR when compiling for Unicode. Which you are obviously doing, given that you are passing TCHAR-based argv[] values to LPCWSTR parameters, which will only compile if TCHAR is wchar_t.
IPersistFile::Save() takes only a Unicode string as input, regardless of what TCHAR maps to. You are converting the char* value from __argv[] from ANSI to Unicode, so you may as well just get a Unicode string from argv[] to begin with, and omit the call to MultiByteToWideChar() altogether.
There is no good reason to mix ANSI and Unicode strings like this. This is something the MSDN example is getting wrong.
And since your function parameters are working with Unicode strings, you should use the IShellLinkW interface directly instead of the TCHAR-based IShellLink interface.
Try this:
#include "stdafx.h"
#include "windows.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink, LPCWSTR lpszDesc)
{
HRESULT hres;
IShellLinkW* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(lpszPathLink, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
}
void _tmain(int argc, TCHAR *argv[])
{
if (argc > 3)
CreateLink(argv[1], argv[2], argv[3]);
}
Visual Studio generates stdafx.h and stdafx.cpp when you are using new project wizard. If Create empty project checkmark is marked, it will not generate them. These files are used to build a precompiled header file Projname.pch and a precompiled types file Stdafx.obj
For small projects you can eventually remove #include "stdafx.h", but it would be better to create new project with Create empty project unmarked.

Using BASS_StreamCreateFile in WPF

BASS_StreamCreateFile(path,offset,length,BassFlags) always returns '0'. I am not understanding how to use this function. Need help on the usage of BassFlags.
PS : Using this with the help of WPF Sound Visualization Library.
Since 0 only informs you that there's an error, you should check what kind of error it is:
int BASS_ErrorGetCode();
This gives you the errorcode for the recent error.
Here's the list of possible error codes (= return values):
BASS_ERROR_INIT // BASS_Init has not been successfully called.
BASS_ERROR_NOTAVAIL // Only decoding channels (BASS_STREAM_DECODE) are allowed when using the "no sound" device. The BASS_STREAM_AUTOFREE // flag is also unavailable to decoding channels.
BASS_ERROR_ILLPARAM // The length must be specified when streaming from memory.
BASS_ERROR_FILEOPEN // The file could not be opened.
BASS_ERROR_FILEFORM // The file's format is not recognised/supported.
BASS_ERROR_CODEC // The file uses a codec that is not available/supported. This can apply to WAV and AIFF files, and also MP3 files when using the "MP3-free" BASS version.
BASS_ERROR_FORMAT // The sample format is not supported by the device/drivers. If the stream is more than stereo or the BASS_SAMPLE_FLOAT flag is used, it could be that they are not supported.
BASS_ERROR_SPEAKER // The specified SPEAKER flags are invalid. The device/drivers do not support them, they are attempting to assign a stereo stream to a mono speaker or 3D functionality is enabled.
BASS_ERROR_MEM // There is insufficient memory.
BASS_ERROR_NO3D // Could not initialize 3D support.
BASS_ERROR_UNKNOWN // Some other mystery problem!
(from bass.h)
Also make shure you have initialised BASS properly - BASS_Init() must get called before you create a stream:
BOOL BASS_Init(
int device, // The device to use... -1 = default device, 0 = no sound, 1 = first real output device
DWORD freq, // Output sample rate
DWORD flags, // A combination of flags
HWND win, // The application's main window... 0 = the current foreground window (use this for console applications)
GUID *clsid // Class identifier of the object to create, that will be used to initialize DirectSound... NULL = use default
);
Example:
int device = -1; // Default device
int freq = 44100; // Sample rate
BASS_Init(device, freq, 0, 0, NULL); // Init BASS

Segfault on very simple source

I'm trying to write a simple script using the FreeType library. The segfault is occurring during execution of the FT_Set_Pixel_Sizes method, though I'm using it correctly. Any help would be great. Here's the full code:
#include <ft2build.h>
#include FT_FREETYPE_H
main() {
FT_Library library;
FT_Face face;
FT_GlyphSlot slot;
FT_UInt glyph_index = 30;
char* font_file = "/usr/share/fonts/truetype/freefont/FreeMono.ttf";
// Render font
FT_New_Face(library, font_file, 0, &face);
FT_Set_Pixel_Sizes(face, 0, 16); /* THIS LINE IS CAUSING THE SEGFAULT */
slot = face->glyph;
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
}
You did not initialize your Library variable : see FT_LIBRARY documentation. You should use FT_Init_FreeType :
FT_Init_FreeType
Defined in FT_FREETYPE_H (freetype/freetype.h).
FT_EXPORT( FT_Error ) FT_Init_FreeType( FT_Library *alibrary );
Initialize a new FreeType library object. The set of modules that are
registered by this function is determined at build time.
output alibrary A handle to a new library object.
return FreeType error code. 0 means success.
You could first get used to this library following this tutorial. Take care to check the return values too ...
You have not initialized your library.
FT_Library library;
error = FT_Init_FreeType(&library);
if (error) { /* report error and exit */ }
You also have to check return values of functions like shown above. For instance, FT_New_Face returns an error (as it probably does in your case), you must not access face because it is left in an undefined state.

Resources