I'm interested in overriding the entry point in my WinUI 3.0 Desktop App to control the message pump. It doesn't appear to be as simple as redefining the static function
static auto Start(winrt::Microsoft::UI::Xaml::ApplicationInitializationCallback const& callback);
in the applications child class. I'm a bit confused even, if the entry point isn't still wWinMain, because if it is, it isn't defined in the solution. I haven't tried setting the Linker option to some other entry point, because I saw mentioned that doing so skips static member pre-processing, and I figured I'd find out what that meant before I started messing around. So how do I capture the entry point?
This has probably been generated by the tooling you use. If you don't use any special tooling or/and have chosen a fancy compiler, you should be able to do it yourself.
If you choose Microsoft tooling, typically C++/WinRT with C++ and Visual Studio, then WinMain is generated probably in a file named App.xaml.g.hpp (to find that, just start debug, it should get you right in that WinMain).
To use your own, define DISABLE_XAML_GENERATED_MAIN somewhere (note it works for C# too):
And add for example this to your appp.xaml.cpp file:
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nShowCmd)
{
winrt::init_apartment(winrt::apartment_type::single_threaded);
// put your fancy code somewhere here
::winrt::Microsoft::UI::Xaml::Application::Start(
[](auto&&)
{
// and here (default is like this)
// ::winrt::make<::winrt::MyNamespace::MyApp::implementation::App>();
});
return 0;
}
Related
Informs the provider that a directory enumeration is starting
`
PRJ_START_DIRECTORY_ENUMERATION_CB PrjStartDirectoryEnumerationCb;
HRESULT PrjStartDirectoryEnumerationCb(
const PRJ_CALLBACK_DATA *callbackData,
const GUID *enumerationId
)
{...}
`
I am confused how to use this function.
You're looking at a callback (a generic programming concept, not specific to Win32), which is usually a reference to a function that you have to write yourself. In order to have the C/C++ compiler check that you've defined your callback function correctly, and to simplify usage of such callbacks, a typedef is often used. The Win32 API often uses all caps to define types of callbacks. In this case, PRJ_START_DIRECTORY_ENUMERATION_CB is the type of the function pointer (a pointer to the callback function that you have to write), and it is defined in projectedfslib.h as:
typedef
_Function_class_(PRJ_START_DIRECTORY_ENUMERATION_CB)
HRESULT
(CALLBACK PRJ_START_DIRECTORY_ENUMERATION_CB)(
_In_ const PRJ_CALLBACK_DATA* callbackData,
_In_ const GUID* enumerationId
);
This definition has a lot of excess stuff in it that helps the Microsoft toolset validate various things related to the usage of this type of function pointer. When writing your own function that works for this type of callback, you don't necessarily have to repeat a lot of the things that are used in the typedef. The MSDN documentation for callbacks often shows an example of how you would write the method signature for your callback, and that example is usually simplified to strip off the excess stuff that the toolset needs, leaving the stuff the developer needs to define when writing their callback.
In this case, the example function is called PrjStartDirectoryEnumerationCb, but there is no function defined with that name. It's up to you to define a function that looks like what you see on MSDN. It doesn't have to have the same name -- you can name it whatever you like, and then you use your function's name anywhere the callback is needed.
HRESULT MyCallback(const PRJ_CALLBACK_DATA *callbackData, const GUID* enumerationId)
{
// implement your callback here
}
In rewriting the API for an existing C++ DLL into a Windows 10 Universal component, how to model generic 'context' parameters for the caller to define and use? The original API was:
typedef void (*My_Callback)
(const int deviceHandle,
void *pContext);
I am trying to rewrite as
delegate void My_Callback(const int deviceHandle, ???? context);
Since the parameters must be passed across the Windows Runtime ABI, it cannot be a void *. What would make sense in its place?
I am trying to create a window with a certain class type ("VSDebugger CDataTipWnd"), however, when I run CreateWindowEx it fails, and GetLastError tells me that the class wasn't found. Here is the code for reference, though it shouldn't matter:
const Win32WindowStyles dwStyle = Win32WindowStyles.WS_POPUP;
IntPtr wnd = NativeMethods.CreateWindowEx(0L, "VSDebugger CDataTipWnd", "MyWindow",
dwStyle, 100, 100, 100, 100, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
I am running as a plug-in in the process and I know that a Window of this class is created before (I made sure of that using Winspector/Spy++), yet, when I try to create a window of this type myself, it doesn't work and I can't figure out why.
The documentation says that the "The class name can be any name registered with RegisterClass or RegisterClassEx, provided that the module that registers the class is also the module that creates the window. The class name can also be any of the predefined system class names. For a list of system class names, see the Remarks section." is it possible that the RegisterClass was indeed created in another module (dll/exe)? Does merely creating a class in another module make it inaccessible by name from another module?? If so, can I still find that class somehow and create a window with it?
Thanks!
Vitaly
You are passing IntPtr.Zero to the HINSTANCE argument.
The HINSTANCE of the module (EXE or DLL) which registered the class must be provided to CreateWindowEx.
If you think the main EXE registered the class then you can get its HINSTANCE via GetModuleHandle(IntPtr.Zero).
If another DLL registered the class then you'll need some way to know which one and get its HINSTANCE/HMODULE (the two are the same these days).
That's probably the case. Does the program provide an API to do this? You mention you're running as a plugin to it - I'd think that'd be the way to do it.
Is it possible to pass a pointer to an object into a DLL, initialize it, and then use the initialized pointer in the main application? If so how? Are there any good articles on the subject, perhaps a tutorial?
I have read this article http://msdn.microsoft.com/en-us/library/ms235460.aspx But that did not seem to get me any where. Maybe I am misinterpreting it...
Yes, this is fine, but assuming your DLL has dynamically allocated the data being pointed to by the buffer, you must be careful about how you free it. There are a few ways to deal with this:
The DLL documents a method by which one should free the data (i.e., CoTaskFree)
The DLL exposes a function that should be called to later free the data
The DLL and the caller are using a common DLL-based runtime; this allows the caller to use the C++ delete operator
Yes.
Assuming you are using Microsoft Visual Studio as your development environment you can export a class rather directly from a dll. Add a define to your dll project something like BUILDING_THE_DLL and the following code snippit will export a c++ class wholesale from the dll.
#ifdef BUILDING_THE_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif
class EXPORT DllClass
{
....
};
This is a highly coupled solution and only works if you build the application and its dll using the same development environment, and rebuild both whenever the class definition changes in any way. this method is heavilly used by the MFC library.
To achieve a greater independence between the dll and app, one typically defines a relatively immutable interface and uses that to make builds more independent, and possibly use different build environments.
An implementation in your dll would look something like this:
struct IMyInterface {
virtual void Destroy() =0;
virtual void Method() = 0;
};
class MoDllObject : public IMyInterface
{
// implementation
};
bool EXPORT DllGetInterface(IMyInterface** ppOut)
{
*ppOut = new MyDllObject();
return true;
}
Is it possible to have a COM method which passes a HWND? With the following method in my object CoCreateInstance returns DISP_E_BADVARTYPE (0x80020008):
STDMETHODIMP ShowDialog(HWND hWndParent);
So far, I'm getting round this problem by passing an OLE_HANDLE then casting it but it feels like a cludge:
STDMETHODIMP ShowDialog(OLE_HANDLE hWndParent);
I think that HWND is a pointer to a struct thats why you can't use it in the IDL.
If you look at Microsoft Typelibs you will see all sort of variation on how to pass a handle (From int to long to HANDLE).
Your interface is probably registered as "dual", and HWND is not one of the types supported by OLE automation. Does your interface need to be IDispatch-compatible (do you need to call it from scripting or late-bound languages)? If not, deriving from IUnknown rather than IDispatch and not registering as dual will help you out.
NB: Casting is okay as long as you are only using the method in-process.