Win32. Enable visual styles in dll - c++

I've got no experience in C++ and Win API so sorry if this question is nooby. I've got DLL where I create some components, MessageBox for example. I added pragma comment to enable visual styles and it does not work (and it shouldn't as I know from this answer: windows 7 style for combobox on internet explorer toolbar, how?
Dll code(omit export and so on):
#include "stdafx.h"
#include "my-dll.h"
#include <Windows.h>
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
MYDLL_API int fnmydll(void)
{
MessageBox(NULL, L"Message", NULL, 0);
return 42;
}
Then I invoke this dll function from my app:
#include <iostream>
#include <Windows.h>
#include "my-dll.h"
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
fnmydll();
return 0;
}
And I've got my message box but without visual styles. As far as I understand I should activate context when my dll is invoked but MSDN has no examples how to do it. Could you please give me such example or at least explain what is going on in more details? Because I can't even understand why function BOOL GetCurrentActCtx(_Out_ HANDLE *lphActCtx); receives pointer to ACTCTX but has signature with some HANDLE type.

If you want your DLL to use visual style aware controls, i.e. comctl32 v6, even if your host application does not use it, you have to use Activation Context API. Here's an example on how to use it:
HANDLE hActCtx;
ACTCTX actCtx;
ZeroMemory(&actCtx, sizeof(actCtx));
actCtx.cbSize = sizeof(actCtx);
actCtx.hModule = hInst;
actCtx.lpResourceName = MAKEINTRESOURCE(2);
actCtx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID;
hActCtx = CreateActCtx(&actCtx);
if (hActCtx != INVALID_HANDLE_VALUE) {
ULONG_PTR cookie;
ActivateActCtx(hActCtx, &cookie);
// Do some UI stuff here; just show a message for example
MessageBox(NULL, TEXT("Styled message box"), NULL, MB_OK);
DeactivateActCtx(0, cookie);
ReleaseActCtx(hActCtx);
}
Here hInst is the module handle of your DLL, you can save it in a global variable in DllMain or use GetModuleHandle function to get it. This sample implies your DLL stores Common Controls version 6.0 manifest in its resources with ID 2.
You can call CreateActCtx only once when your DLL initializes, and ReleaseActCtx when it's not needed any more. Call ActivateActCtx before creating any windows and call DeactivateActCtx before returning control to application.

Related

CWinApp CFrameWindow not shown

i'm trying to create window using CFrameWindow, i used code from "Simulation for applied graph theory using Visual C++" but it didn't had entry point, so it doesn't work any way. So i simplified it as much as i could and now when application is launched in release mode window doesn't appear and in debug mode it throws error that assertion failed. I used MSVS Visual C++ -> General -> Empty project with "Use of MFC" set to Use MFC in a Shared DLL.
Here is the code :
#include <afxwin.h>
class MyWnd : public CFrameWnd
{
public:
MyWnd() { Create(0, "MyWnd"); }
~MyWnd() { }
};
class MyApp : public CWinApp
{
public:
virtual BOOL InitInstance()
{
m_pMainWnd = new MyWnd;
m_pMainWnd->ShowWindow(m_nCmdShow);
return TRUE;
}
};
int CALLBACK WinMain (_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
MyApp myApp;
myApp.InitInstance();
myApp.Run();
}
EDIT: updated to call MyApp.Run(), but it still doesn't display anything, also checked Subsystem, none was selected, tried Console, Windows, Native, compiled only with Windows but didn't help.
After InitInstance you should call CWinApp::Run in order to start message pumping.
Also, Run() blocks the WinMain function until it exits. Without Run(), your WinMain simply terminates before you see the window.
So, it displays blank white window with titlebar when i make myApp global with myApp.Run() or without it.
EDIT: It worked on my laptop win10, but on pc win7 same code didn't work, so on pc in project properties -> character set was Multibyte, after changing it to Unicode, it started showing window on pc also.

win32 - Dialog inside .dll

I want to a create .dll, which shows some dialog.
In my .dll I have this code:
HWND hDlg = CreateDialogParam(NULL, MAKEINTRESOURCE(IDD_RANKING_DIALOG), NULL, msgProc, NULL);
if (!hDlg) {
ShowError(GetLastErrorAsString().c_str());
return false;
}
ShowError calls Message box and GetLastErrorAsString() just calls standard GetLastError and converts to string.
I have this output:
The specified resource type cannot be found in the image file.
Then I have a standard win32 Window application and there I call method, which calls the mentioned code.
DialogTest test;
test.showDialog(); // calls functionality from .dll
What I am doing wrong? Do I need to link resource files to .dll?
I am using Visual studio 2010 and dialog is specified in my resource file (.rc).
The error code and message are accurate: The resource cannot be found where you instructed the system to go looking for it: The executable image that was used to start the process, not your DLL. The behavior is documented (see CreateDialogParam):
hInstance [in, optional]
Type: HINSTANCE
A handle to the module which contains the dialog box template. If this parameter is NULL, then the current executable is used.
Since you have the dialog template stored inside your DLL, you will have to pass the HINSTANCE that identifies your DLL. There are a number of ways to get the correct value, but passing NULL or GetModuleHandle(NULL) won't work. Both of these return the module handle to the executable image that started the process (not your DLL).
The easy solution: Pick the hInstance passed into your DllMain and store it in a global variable for later use.
HINSTANCE g_hInst = NULL;
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) {
switch ( fdwReason ) {
case DLL_PROCESS_ATTACH:
g_hInst = hinstDLL;
break;
default:
break;
}
return TRUE;
}
The robust solution: This solution can be used anywhere, in a DLL, an EXE, or a static LIB. Only down-side: It relies on undocumented features of Microsoft's linker. Don't worry, though, it won't fail silently.
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISMODULE ((HINSTANCE)&__ImageBase)
HINST_THISMODULE will always hold the correct value, regardless of where it is used.1)
The same can be achieved using official interfaces (GetModuleHandleEx) as well. The following solution can be used from an EXE, a DLL, or a static LIB as well, so long as you make sure to compile and link the function into the respective module:
HMODULE GetCurrentModuleHandle() {
HMODULE hModule = NULL;
GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)GetCurrentModuleHandle,
&hModule );
return hModule;
}
This returns an HMODULE, not an HINSTANCE. This is not an issue, though, since they are the same thing2).
1) From Accessing the current module’s HINSTANCE from a static library
2) What is the difference between HINSTANCE and HMODULE?
You specified NULL as the first parameter to CreateDialogParam. If you want to load the dialog resource file from the Win32 Window Application, you should use this instead:
HWND hDlg = CreateDialogParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_RANKING_DIALOG), NULL, msgProc, NULL);
However, if you want to load it from the DLL itself, you should replace the first parameter with the HINSTANCE parameter from the DllMain entry point function of the DLL.

Adding MFC to existing Win32 C++ Causing Errors/Crashes

I really want to use some features from MFC but its been a pain to get working.
All I originally wanted to do was add two Spin Control and their respective Edit Controls. Once I implemented their appropriate methods to set Range, I found out I needed to use MFC.
So VS complain no MFC. So I go to project properties and add Use MFC shared DLL. Run it, Crash!
Unhandled exception at 0x5964D8D2 (mfc120ud.dll) in Win32Project1.exe: 0xC0000005: Access violation reading location 0x00000000
So I tried Static, ERRORS! Lots of linker errors, to many to list.
So I went back to Shared. The error occurs right in this area.
/////////////////////////////////////////////////////////////////////////////
// export WinMain to force linkage to this module
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow);
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, int nCmdShow)
#pragma warning(suppress: 4985)
{
// call shared/exported WinMain
return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}
with an arrow at the last }
Locals shows the value of hInstance as red with +
hInstance 0x000d0000 {Win32Project1.exe!_IMAGE_DOS_HEADER ImageBase} {unused=9460301 } HINSTANCE *
and at lpCmdLine
+ lpCmdLine 0x00831f8c L"" wchar_t *
This is beyond my expertise of debugging and quite frankely would consider another alternative to the spin box that doesn't use MFC, but it seems like I'm need MFC more and more as I want to include more functionality, so it would be nice to get MFC working, but it also seems a lot more fragile. Perhaps to sensitive for a crude programmer such as myself.
I'm wondering if #includes could be a cause of this error? Either the order? Or lack thereof?
Here is what I have so far in stdafx.h
#pragma once
#pragma comment ( lib, "user32.lib" )
#pragma comment ( lib, "comctl32.lib" )
#pragma comment ( lib, "winmm.lib")//to play audio
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#include "targetver.h"
//#include <WinSDKVer.h>
//#include <afxwin.h>
#include <afxcmn.h>//for spinControl
#include <Afx.h>
#include <stdio.h>
#include <tchar.h>
#include "iostream"
#include "string.h"
#include <math.h>
//#include <ctime>//more time related stuff
#include <fstream>//for file io
#include <thread>//for threads
//#include <chrono> //for time related stuff
//#include <windows.h>
#include <Mmsystem.h>//to play audio
#include <commctrl.h>
#include <atlstr.h>//for some type of string
#include <io.h>
#include <fcntl.h>
#include <commctrl.h> //For button sytles, maybe other styles
This can never work. Remove your WinMain.
You Need a CWinApp object for your application. And with this CWinApp Object thee is a MFC specific WinMain entry point.
The MFC relays on an internal singleton that points to your CWinApp object. Without it nearly everything can fail, and can throw ASSERTs.
I would suggest that you create a sample MFC app, then move the MFC code from the sample app to your Win32 app. If the Win32 app is smaller, you can instead move the Win32 code to the MFC app.
Typically, instead of WinMain, you would use CWinApp class from the sample app.
If you do not intend to use the MFC UI classes & only wish to use some supporting classes like CString etc, then you can create a sample console app with MFC support which will tell you how to use CString in console app. The console app will give you an insight on how to add the required headers in your Win32 project.
As the previous answers have mentioned, but I thought I'd clarify - try adding a CWinApp (or CWinAppEx) object in your code to define the WinMain, for example:
class MyApp : public CWinApp
{
public:
virtual BOOL InitInstance()
{
// Add initialisation code here e.g. show a dialog or main window, etc.
return TRUE; // enter the message loop;
// could return FALSE to just exit the application if for example the
// dialog response is all you need to then quit.
}
};
// And somewhere in your code be sure to instantiate the object so that it can be linked
MyApp theApp;

GetModuleHandle(NULL) vs hInstance

When programming using the Windows API, I've always made the HINSTANCE from WinMain a global variable immediately. If I want to make an OK button, I'd do it like so (given global HINSTANCE g_hInstance):
return CreateWindow("BUTTON", "OK", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 10, 10, 100, 30, exampleParentWindow, EXAMPLECHILDID, g_hInstance, NULL);
but lately I've been seeing the instance handle determined without having to be passed as a parameter or clogging up the global namespace, using a call to GetModuleHandle(NULL)*. So, the example above would look like this:
return CreateWindow("BUTTON", "OK", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON, 10, 10, 100, 30, exampleParentWindow, EXAMPLECHILDID, GetModuleHandle(NULL), NULL);
*If your compiler supports it, you can write GetModuleHandle(nullptr) and the statement will have the same result.
What's the advantage (if any) of calling GetModuleHandle(NULL) over explicitly specifying the instance handle?
Fine Print: I know this has an answer, but it has not been phrased as its own question on StackOverflow.
In an EXE, it does not make any difference. hInstance from WinMain() and GetModuleHandle(NULL) both refer to the same HINSTANCE (the module of the .exe file). But it does make a difference if you are creating windows inside of a DLL instead, since you have to use the DLL's hInstance but GetModuleHandle(NULL) will still return the HINSTANCE of the EXE that loaded the DLL.
HMODULE WINAPI GetModuleHandle( _In_opt_ LPCTSTR lpModuleName );
Give the module handle of the module name passed.If you are passing NULL, the you get the module handle of the EXE which is currently running.
If you specifically name the module name, you get the module handle of that dll which is mapped to the process address space.
The use is that when you are trying to call a function exported by the dll, or trying to use a dialog template in side that dll.At that time if you use the HMODULE returned form GetMoudleHandle(NULL) your code wont work.
Just to add my two-cents to these answers. In case you need to get the module handle from within a DLL (and don't want to, or can't save it in a global variable from the DllMain call) you can use this function to get it instead:
HMODULE getThisModuleHandle()
{
//Returns module handle where this function is running in: EXE or DLL
HMODULE hModule = NULL;
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)getThisModuleHandle, &hModule);
return hModule;
}
One potential gain you get from using GetModuleHandle(NULL) over directly using the WinMain HINSTANCE comes more from architecture. If you want to provide a platform-independent system that runs on linux/windows/whatever you can have a layer that does platform-dependent translations. If that's the case you don't want platform dependent objects such as HINSTANCE showing up in the main application code. So, to circumvent that platform-dependence I put GetModuleHandle(NULL) in the constructor of the platform-dependent class which has the same effect that direct use of the WinMain HINSTANCE does but that abstracts that specific functionality out of the main codebase itself.

C++ - Basic WinAPI question

I am now working on a some sort of a game engine and I had an idea to put everything engine-related into a static library and then link it to my actual problem.
Right now I achieved it and actually link that library and every functions seem to work fine, except those, which are windows-related.
I have a chunk of code in my library that looks like this:
hWnd = CreateWindow(className, "Name", WS_OVERLAPPED | WS_CAPTION | WS_EX_TOPMOST,
0, 0,
800, 600,
NULL, NULL, GetModuleHandle(NULL), this);
if (hWnd) {
ShowWindow(hWnd, SW_NORMAL);
UpdateWindow(hWnd);
} else {
MessageBox(NULL, "Internal program error", "Error", MB_OK | MB_ICONERROR);
return;
}
When this code was not in the library, but in the actual project, it worked fine, created the window and everything was ok. Right now (when I'm linking to my library that contains this code) CreateWindow(...) call returns NULL and GetLastError() returns "Operation succesfully completed" (wtf?).
Could anybody help me with this? Is it possible to create a window and display it using a static library call and why could my code fail?
Thank you.
Ah, maybe you've run into this problem described in an MSDN blog:
If you're writing a static library, you may have need to access the HINSTANCE of the module that you have been linked into. You could require that the module that links you in pass the HINSTANCE to a special initialization function, but odds are that people will forget to do this.
If you are using a Microsoft linker, you can take advantage of a pseudovariable which the linker provides.
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
The pseudovariable __ImageBase represents the DOS header of the module, which happens to be what a Win32 module begins with. In other words, it's the base address of the module. And the module base address is the same as its HINSTANCE.
So there's your HINSTANCE.
So, instead of passing GetModuleHandle(NULL) to CreateWindow, try ((HINSTANCE)&__ImageBase) (make sure it is declared as shown in the blog first).
Edit:
From the comments in that blog entry, one mentions the use of GetModuleHandleEx(), perhaps this is a more Compiler/Linker-agnostic approach.