#define _UNICODE not working with MinGW + CodeBlocks - winapi

usually i use visual studio, but i switched to mingw, i like to make my apps easily changeable from unicode and multi byte, in my mingw project i have my defines and includes like this:
#define WIN32_LEAN_AND_MEAN
#define WINVER 0x0700
#define _UNICODE
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#define WND_MAIN_CLASS _T("MainWindowFrame")
then i register and create my window e.g.
WNDCLASSEX wc;
...
wc.lpszClassName = WND_MAIN_CLASS;
RegisterClassEx(&wc);
hwnd = CreateWindowEx(0, WND_MAIN_CLASS, _T("Main Window"),
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInst, NULL);
but when i go to compile i get errors that it cannot convert wchar_t to CHAR* on the WNDCLASSEX lpszClassName and the CreateWindowEx on the Class name and window title.
if i right click and go to declaration of createwindowex and WNDCLASSEX, it comes up with these from winuser.h:
typedef WNDCLASSEXW WNDCLASSEX,*LPWNDCLASSEX,*PWNDCLASSEX;
#define CreateWindowEx CreateWindowExW
if i comment out the define _UNICODE it compiles and works with no problems

When compiling unicode apps you should probably define both UNICODE and _UNICODE. The windows headers use UNICODE and the MS C runtime uses _UNICODE

Related

GDI+ methods are missing

So I'm trying to use the method Bitmap::GetHistogram from GDI+ but apparently it doesn't exist. I already made sure to initialize everything with
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
at the start of WinMain, here's the problematic snippet:
UINT numEntries;
Gdiplus::Bitmap myBitmap(pszFilePath);
Gdiplus::Image myImage(pszFilePath);
UINT iHeight = myImage.GetHeight(); // works
UINT iWidth = myImage.GetWidth(); // works
myBitmap.GetHistogramSize(HistogramFormatRGB, &numEntries); // not defined
These are all the header files included:
#include <Unknwn.h>
#include <windows.h>
#include <Gdiplus.h>
#include <stdio.h>
#include <iostream>
#include <commdlg.h>
#include <commctrl.h>
#include <winioctl.h>
#include <Objbase.h>
#include <shobjidl.h>
#include <objidl.h>
#include <strsafe.h>
The method simply isn't' there:
What might causing this and how do I fix it?
I'm curious as to why this happened
Because the method needs the GDIPVER >= 0x0110 in gdiplusbitmap.h:
#if (GDIPVER >= 0x0110)
...
inline Status
Bitmap::GetHistogram(
IN HistogramFormat format,
IN UINT NumberOfEntries,
_Out_writes_bytes_(sizeof(UINT)*256) UINT *channel0,
_Out_writes_bytes_(sizeof(UINT)*256) UINT *channel1,
_Out_writes_bytes_(sizeof(UINT)*256) UINT *channel2,
_Out_writes_bytes_(sizeof(UINT)*256) UINT *channel3
)
{
return DllExports::GdipBitmapGetHistogram(
static_cast<GpBitmap *>(nativeImage),
format,
NumberOfEntries,
channel0,
channel1,
channel2,
channel3
);
}
inline Status
Bitmap::GetHistogramSize(
IN HistogramFormat format,
OUT UINT *NumberOfEntries
)
{
return DllExports::GdipBitmapGetHistogramSize(
format,
NumberOfEntries
);
}
#endif // (GDIPVER >= 0x0110)
All recent OS (>= Vista) have GDIPlus 1.1. But if you do not specify GDIPVER to 0x0110 to enable the function of version 1.1, the default version will be specified as 1.0 in gdiplus.h:
// Define the Current GDIPlus Version
#ifndef GDIPVER
#define GDIPVER 0x0100
#endif

Cross-platform definition of _byteswap_uint64 and _byteswap_ulong

Visual Studio defines _byteswap_uint64 and _byteswap_ulong in stdlib.h.
Am I right to assume, that this is not standard and won't compile on Linux or Darwin?
Is there a way to define these includes in a cross-platform way?
Google's CityHash source code uses this code:
https://github.com/google/cityhash/blob/8af9b8c2b889d80c22d6bc26ba0df1afb79a30db/src/city.cc#L50
#ifdef _MSC_VER
#include <stdlib.h>
#define bswap_32(x) _byteswap_ulong(x)
#define bswap_64(x) _byteswap_uint64(x)
#elif defined(__APPLE__)
// Mac OS X / Darwin features
#include <libkern/OSByteOrder.h>
#define bswap_32(x) OSSwapInt32(x)
#define bswap_64(x) OSSwapInt64(x)
#elif defined(__sun) || defined(sun)
#include <sys/byteorder.h>
#define bswap_32(x) BSWAP_32(x)
#define bswap_64(x) BSWAP_64(x)
#elif defined(__FreeBSD__)
#include <sys/endian.h>
#define bswap_32(x) bswap32(x)
#define bswap_64(x) bswap64(x)
#elif defined(__OpenBSD__)
#include <sys/types.h>
#define bswap_32(x) swap32(x)
#define bswap_64(x) swap64(x)
#elif defined(__NetBSD__)
#include <sys/types.h>
#include <machine/bswap.h>
#if defined(__BSWAP_RENAME) && !defined(__bswap_32)
#define bswap_32(x) bswap32(x)
#define bswap_64(x) bswap64(x)
#endif
#else
#include <byteswap.h>
#endif
I'm not aware of a cross-platform and efficient way of doing that. If you use GCC you can use the builtin byteswap like:
uint32_t __builtin_bswap32 (uint32_t x)
Those are fast but certainly not portable... unless you wrap the various versions under the appropriate ifdefs
Cheers
Francesco

WIN API GetFileSizeEx() function, was not declared in this scope

In my c++ class, I want use WIN API GetFileSizeEx() function. When I compile my code, the compilator said:
"error: 'GetFileSizeEx' was not declared in this scope".
However, others functions like CreateFile() or WriteFile() work perfectly.
In my class header, I declare this :
#if defined(WINVER) && WINVER==0x0602 /* windows 8 */
#define WINVER 0x0602
#define _WIN32_WINNT 0x0602
#elif defined(WINVER) && WINVER==0x0601 /* windows 7 */
#define WINVER 0x0601
#define _WIN32_WINNT 0x0601
#elif defined(WINVER) && WINVER==0x0600 /* windows vista and server 2008 */
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#elif defined(WINVER) && WINVER==0x0502 /* server 2003 */
#define WINVER 0x0502
#define _WIN32_WINNT 0x0502
#elif defined(WINVER) && WINVER==0x0501 /* windows xp */
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#endif
#include <windows.h>
#include <winbase.h>
#include <string>
In my .cpp class:
Test::Test()
{
hFile = CreateFile(TEXT("conf/configure_tool.txt"),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
canAcces = false;
}else
{
if(GetFileSizeEx(hFile,&sized) != 0)
{
canAcces = true;
}
}
}
Have you an idea to resolve my problem ?
From the documentation:
Minimum supported client Windows XP [desktop apps only]
So you need to ensure that you have defined WINVER to be 0x0501 or greater.
If that doesn't solve the problem then the likely cause is that you are using a deficient SDK. Perhaps from an old version of a non-MS compiler. Make sure that you have an up-to-date SDK.
It must be said that the conditional code in the question that attempts to define _WIN32_WINNT is a little odd. Why don't you define _WIN32_WINNT at the same time as you define WINVER?

Ambigous Pointers in Visual C++

Hello everyone,
I am a novice to Win32 API programming in Visual C++. I am using Microsoft Visual Studio 2008 Professional Edition. I am facing a of bit confusion regarding pointers. Please note though I may be a novice to Windows programming, I am not a novice in C or C++ therefore I understand the concept of pointers well.
The pointer which is causing a problem is related with a date and time picker control in a dialog box. Now according to the msdn documentation the date and time picker communicates to the application using WM_NOTIFY messages and the LPARAM in the message will be the pointer to the NMHDR structure. That is-:
'A date and time picker (DTP) control sends notification codes when it receives user input or processes and reacts to callback fields. The parent of the control receives these notification codes in the form of WM_NOTIFY messages.'
Now I can access the NMHDR structure by just typecasting the LPARAM to a pointer of NMHDR when I receive an WM_NOTIFY message. That is as follows-:
case WM_NOTIFY:
if ((((NMHDR*)lparam)->idFrom == IDC_DATETIMEPICKER)&&
((NMHDR*)lparam)->code == DTN_DATETIMECHANGE)
{ LPNMDATETIMECHANGE lpChange=(LPNMDATETIMECHANGE)lparam;
DisplayTime(&(lpChange->st));
MessageBox(NULL,"wm_notify","test",MB_OK);
}
return TRUE;
But look at the fourth line of this code fragment. I am casting the same lparam, which I just casted to a NMHDR structure, into a NMDATETIMECHANGE structure.
My question is how is this possible ? How am I casting a single parameter into two different pointers that reference two different structures ? The NMHDR and LPNMDATETIMECHANGE structures are fundamentally different structures. You can check here-: NMHDR and NMDATETIMECHANGE
How is this possible? I know it is possible to store the value of a pointer in some other variable with a different data-type all together and again cast it back when we want to use it. But how is it possible to have a single pointer point to two different structures altogether ? I mean I don't think that the NMHDR and NMDATETIMECHANGE structures are the same entity in the memory so how can a single pointer reference both of them at the same time ? They have two different memory addresses altogether I hope? Oh, and please note that this code is tested, it works. My source code is as follows-:
#include <Windows.h>
#include <CommCtrl.h>
#include <cstdio>
#include "resource.h"
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DialogFunc(HWND, UINT, WPARAM, LPARAM);
VOID InitOptions(HWND);
VOID DisplayTime(SYSTEMTIME*);
char szWinName[]="Timer Main Window";
HWND hDlg=NULL;
HINSTANCE hInst;
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
LPSTR lpszArgs, int nWinMode)
{
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
wndclass.cbSize=sizeof(WNDCLASSEX);
wndclass.hInstance=hThisInst;
wndclass.lpszClassName=szWinName;
wndclass.lpfnWndProc=WindowFunc;
wndclass.style=0;
wndclass.hIcon=LoadIcon(hThisInst,MAKEINTRESOURCE(IDI_ICON1));
wndclass.hIconSm=LoadIcon(hThisInst,MAKEINTRESOURCE(IDI_ICON2));
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.lpszMenuName=NULL;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH) GetStockObject(LTGRAY_BRUSH);
if(!RegisterClassEx(&wndclass)) return 0;
InitCommonControls();
hInst=hThisInst;
hwnd=CreateWindow(
szWinName,
"Auto Timer (Work in progress)",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hThisInst,
NULL
);
while(GetMessage(&msg, NULL, 0, 0)>0)
{ if (!hDlg||!IsDialogMessage(hDlg,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wparam,
LPARAM lparam)
{
switch(message){
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hDlg=CreateDialog(hInst,MAKEINTRESOURCE(IDD_FORMVIEW),
hwnd,(DLGPROC)DialogFunc);
break;
default:
return DefWindowProc(hwnd,message,wparam,lparam);
}
return 0;
}
BOOL CALLBACK DialogFunc(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam)
{
switch(message)
{
case WM_INITDIALOG:
SendMessage(hwnd,WM_SETICON, ICON_SMALL ,
(LPARAM)LoadIcon(hInst,MAKEINTRESOURCE(IDI_ICON2)));
return TRUE;
case WM_CTLCOLORSTATIC:
if (SendDlgItemMessage(hDlg,IDC_COMBO,CB_GETCOUNT,0,0)<6)
{
InitOptions(hDlg);
}
return (INT_PTR)GetStockObject(WHITE_BRUSH);
case WM_NOTIFY:
if ((((NMHDR*)lparam)->idFrom == IDC_DATETIMEPICKER)&&
((NMHDR*)lparam)->code == DTN_DATETIMECHANGE)
{ LPNMDATETIMECHANGE lpChange=(LPNMDATETIMECHANGE)lparam;
DisplayTime(&(lpChange->st));
MessageBox(NULL,"wm_notify","test",MB_OK);
}
return TRUE;
case WM_COMMAND:
switch LOWORD(wparam)
{ case IDC_BUTTON1:
/*
Button Code here.
*/
if (SendDlgItemMessage(hDlg,IDC_RADIO5,BM_GETSTATE,0,0)==BST_CHECKED)
{ MessageBox(NULL,"radio5","test",MB_OK);
}
return TRUE;
case IDC_RADIO5:
EnableWindow(GetDlgItem(hDlg,IDC_COMBO),TRUE);
EnableWindow(GetDlgItem(hDlg,IDC_DATETIMEPICKER),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_DATETIMEPICKER1),FALSE);
return TRUE;
case IDC_RADIO6:
EnableWindow(GetDlgItem(hDlg,IDC_COMBO),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_DATETIMEPICKER),TRUE);
EnableWindow(GetDlgItem(hDlg,IDC_DATETIMEPICKER1),TRUE);
return TRUE;
default:
return FALSE;
}
case WM_CLOSE:
DestroyWindow(hwnd);
hDlg=NULL;
PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
VOID InitOptions(HWND hDlg){
SendDlgItemMessage(hDlg,IDC_COMBO,CB_ADDSTRING,0,(LPARAM)("1 minute"));
SendDlgItemMessage(hDlg,IDC_COMBO,CB_ADDSTRING,0,(LPARAM)("5 minutes"));
SendDlgItemMessage(hDlg,IDC_COMBO,CB_ADDSTRING,0,(LPARAM)("10 minutes"));
SendDlgItemMessage(hDlg,IDC_COMBO,CB_ADDSTRING,0,(LPARAM)("20 minutes"));
SendDlgItemMessage(hDlg,IDC_COMBO,CB_ADDSTRING,0,(LPARAM)("30 minutes"));
SendDlgItemMessage(hDlg,IDC_COMBO,CB_ADDSTRING,0,(LPARAM)("1 hour"));
SendDlgItemMessage(hDlg,IDC_COMBO,CB_SETCURSEL,0,0);
SendDlgItemMessage(hDlg,IDC_RADIO5,BM_SETCHECK,BST_CHECKED,0);
SendDlgItemMessage(hDlg,IDC_RADIO1,BM_SETCHECK,BST_CHECKED,0);
SendDlgItemMessage(hDlg,IDC_DATETIMEPICKER1,DTM_SETFORMAT,0,(LPARAM)"dd/MMM/yyyy");
EnableWindow(GetDlgItem(hDlg,IDC_DATETIMEPICKER1),FALSE);
}
VOID DisplayTime(SYSTEMTIME *time)
{
char t[500];
sprintf_s(t,"Year=%d\n Month=%d\n Day=%d\n Hour=%d\n Minute=%d\n Seconds=%d\n",
time->wYear,time->wMonth,time->wDay,
time->wHour,time->wMinute,time->wSecond);
MessageBox(NULL,t,"Test",MB_OK);
}
My resource script is the following-:
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_FORMVIEW DIALOGEX 0, 0, 298, 178
STYLE DS_ABSALIGN | DS_SETFONT | DS_SETFOREGROUND | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW | WS_EX_NOACTIVATE
CAPTION "SR-Timer(Work in Progress)"
FONT 10, "Verdana", 400, 0, 0x0
BEGIN
GROUPBOX "Tasks",IDC_STATIC1,11,45,84,103,WS_GROUP,WS_EX_TRANSPARENT
CONTROL "ShutDown",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,19,63,44,10,WS_EX_TRANSPARENT
CONTROL "Restart",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,19,81,40,10,WS_EX_TRANSPARENT
CONTROL "Stand By",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,19,114,46,10,WS_EX_TRANSPARENT
CONTROL "Hibernate",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,19,130,48,10,WS_EX_TRANSPARENT
CONTROL "Log Off",IDC_RADIO7,"Button",BS_AUTORADIOBUTTON,19,98,44,9,WS_EX_TRANSPARENT
GROUPBOX "Timing",IDC_STATIC2,196,44,90,107,WS_GROUP,WS_EX_TRANSPARENT
CONTROL "Pre-set Time",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON,201,56,53,9,WS_EX_TRANSPARENT
GROUPBOX "Presets",IDC_STATIC3,206,65,68,30,0,WS_EX_TRANSPARENT
CONTROL "Specify Time",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON,201,97,54,9,WS_EX_TRANSPARENT
GROUPBOX "Time",IDC_STATIC4,208,106,67,42,0,WS_EX_TRANSPARENT
CONTROL "",IDC_DATETIMEPICKER,"SysDateTimePick32",DTS_RIGHTALIGN | DTS_UPDOWN | WS_DISABLED | WS_TABSTOP | 0x8,213,133,58,11,WS_EX_TRANSPARENT
PUSHBUTTON "Schedule Task",IDC_BUTTON1,184,159,104,14,BS_CENTER,WS_EX_TRANSPARENT
COMBOBOX IDC_COMBO,213,78,57,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP,WS_EX_TRANSPARENT
CONTROL "",IDC_DATETIMEPICKER1,"SysDateTimePick32",DTS_RIGHTALIGN | WS_TABSTOP,213,116,58,13,WS_EX_TRANSPARENT
CONTROL 118,IDC_STATIC,"Static",SS_BITMAP,0,0,299,178
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "Test.ico"
IDI_ICON2 ICON "small.ico"
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_FORMVIEW, DIALOG
BEGIN
BOTTOMMARGIN, 177
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
IDB_BITMAP1 BITMAP "time_back.bmp"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
My resource header is the following-:
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Timer.rc
//
#define IDD_FORMVIEW 101
#define IDI_ICON1 109
#define IDI_ICON2 110
#define IDB_BITMAP1 118
#define IDC_DATETIMEPICKER 1002
#define IDC_RADIO1 1003
#define IDC_RADIO2 1004
#define IDC_RADIO3 1005
#define IDC_RADIO4 1006
#define IDC_BUTTON1 1007
#define IDC_RADIO5 1011
#define IDC_RADIO6 1013
#define IDC_COMBO 1015
#define IDC_STATIC1 1017
#define IDC_STATIC2 1018
#define IDC_STATIC3 1022
#define IDC_STATIC4 1023
#define IDC_COMBO1 1024
#define IDC_DATETIMEPICKER1 1025
#define IDC_RADIO7 1026
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 120
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1027
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
You can make your own VC++ project and test it out to see if I am telling the truth or not. If you are still not convinced then please give me your mail id and I will email you the entire project. Please I need help because this is a problem which goes against my basics of pointers in C. Thank You.
If you look closely, you'll see that NMDATETIMECHANGE contains a NMHDR as its first member, so it is effectively a derived class. (Not strictly a derived class because C doesn't have classes, but it's the C emulation of a derived class.) Casting to NMDATETIMECHANGE is therefore a downcast.
More formally, it's a CONTAINING_RECORD(NMDATETIMECHANGE, hdr, (NMHDR*)lparam) but that's a lot of typing, so most people shortcut it to the direct cast.
typedef struct tagNMDATETIMECHANGE {
NMHDR nmhdr;
DWORD dwFlags;
SYSTEMTIME st;
} NMDATETIMECHANGE, *LPNMDATETIMECHANGE;
Thats the definition of the NMDATETIMECHANGE structure. Note the first member is of type NMHDR . So if you use the pointer to NMDATETIMECHANGE structure you are effectively pointing to the base address of NMHDR. That is the reason you can typecast the LPARAM to NMHDR* and NMDATETIMECHANGE*.

Trying to use SHCreateShellItem, having #include issues

There is a function in called SHCreateShellItem which is declared in <shlobj.h>, but it has been #ifdef'd out based on whether or not _WIN32_IE is greater than or equal to 0x601 (if it is, then the declaration is present). However, even when I define _WIN32_IE to 0x601 before I include <shlobj.h>, MSVC++ still complains that SHCreateShellItem is undeclared.
For example, I cannot get the following to compile:
#define _WIN32_IE 0x601
#include <shlobj.h>
int someFunction (LPITEMIDLIST parent, LPITEMIDLIST child)
{
HRESULT result;
IShellItem *shellObj;
result = SHCreateShellItem (parent, NULL, child, &shellObj);
if (SUCCEEDED(result))
{
// do stuff
}
return SUCCEEDED(result);
}
Do I need to define _WIN32_IE in a different way?
_WIN32_IE is usually defined in your stdafx.h file. You must change it there.
Don't define _WIN32_IE directly, do it implicitly with _WIN32_WINNT (which sets the target platform for the SDK includes)
#define _WIN32_WINNT 0x0600
#include <windows.h>
#include <shlobj.h>

Resources