Win32 API und WPF



  • Jau 😡 und auch das habe ich probiert:

    CoInitializeEx ( NULL, COINIT_APARTMENTTHREADED );
    

    Vlt sollte ich einfach mal meinen Testcode reinstellen:

    #pragma managed
    
    using namespace System;
    using namespace System::Windows;
    using namespace System::Windows::Controls;
    using namespace System::Windows::Forms;
    using namespace System::Windows::Interop;
    
    HwndSource^ TestFkt ( HWND hWnd, int x, int y, int width, int heigt );
    void InitWPF ( RECT rc );
    
    void InitWPF ( RECT rc )
    {
         HWND hWndParent;
    
         if (( hWndParent = GetParent ( g_hWnd )) == NULL )
              hWndParent = GetActiveWindow ( );
    
         MapWindowPoints ( 0, hWndParent, ( POINT* ) &rc, sizeof ( RECT ) / sizeof ( POINT ));
    
         HwndSource^ srcWpfView = TestFkt ( hWndParent, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top );
    
         ShowWindow (( HWND ) srcWpfView->Handle.ToPointer ( ), SW_SHOW );
    }
    
    HwndSource^ TestFkt ( HWND hWnd, int x, int y, int width, int height )
    {
    
         Button^ bWpfButton = gcnew Button ( ); // hier krachts!
    
         bWpfButton->Content = "Testbutton";
         bWpfButton->Opacity = 0.8f;
         bWpfButton->Width   = 120;
         bWpfButton->Height  = 30;
    
         HwndSourceParameters params;
    
         params.ParentWindow = IntPtr ( hWnd );
         params.WindowStyle  = WS_CHILD | WS_VISIBLE;
         params.PositionX    = x;
         params.PositionY    = y;
         params.Width        = width;
         params.Height       = height;
    
         HwndSource^ src = gcnew HwndSource ( params );
    
         src->RootVisual = bWpfButton;
    
         return ( src );
    }
    
    #pragma unmanaged
    
    LRESULT CALLBACK WndProc ( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
    {
         switch ( message ) {
         case WM_CREATE:
    
              RECT rc;
    
              GetWindowRect ( g_hWnd, &rc );
    
              InitWPF ( rc );
    
              return ( 0 );
    ...
    
    int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance,
    				 PSTR szCmdLine, int iCmdShow )
    {
         ::MSG      msg;
         WNDCLASSEX wndclass;
         int        cx, cy;
    
         g_hInst                = hInstance;
    
         CoInitializeEx ( NULL, COINIT_APARTMENTTHREADED );
    
         ZeroMemory ( &wndclass, sizeof ( WNDCLASSEX ));
    
    ...
    

    Irgendwo ein Fehler? Sollte ich irgendwas anders machen?



  • Was ist eigentlich schlussendlich das Ziel?
    Mir schein WinAPI mit WPF zu verwenden ein ziemlicher "Murks".

    Was natürlich nicht dein Problem erklärt oder löst.

    Simon



  • Ich wollte es eigentlich nur probieren und u.U. ein Frontend mit WPF bauen und den Rest DX überlassen (C++). Aber wahrscheinlich werde ich nun doch alles in C/C++ machen.
    Die Frage ist durchaus berechtigt!



  • Die Frage ist eher: Warum machst Du es nicht in C#?

    PS: Ich sehe hier nirgens, dass Du ein
    System::Thread::Thread::CurrentThread->SetApartmentState(ApartmentState.STA);
    machst...



  • Ich habe jetzt versucht den Code

    System::Threading::Thread::CurrentThread->SetApartmentState ( System::Threading::ApartmentState::STA );
    

    in void InitWPF ( ... ) reinzunehmen, die Anwendung schmiert nun mit folgender Meldung ab:

    Eine nicht behandelte Ausnahme des Typs "System.InvalidOperationException" ist in mscorlib.dll aufgetreten.

    Zusätzliche Informationen: Der angegebene COM-Apartmentzustand konnte nicht festgelegt werden.

    Viele Grüße und sorry fürs Nerven 🙄



  • Dann lass mal alle anderen Aufrufe von "CoI*" einfach weg! Du hast den Thread schon anders initialisiert!



  • Habe ich bereits versucht, funktioniert trotzdem nicht, schmiert mit der COM-Apartmentzustands-Meldung ab. Ich gebs auf, danke an alle!



  • Folgendes Projekt geht bei mir wunderbar:

    [System::STAThreadAttribute]
    int main(array<System::String ^> ^args)
    {
      System::Windows::Controls::Button ^btn = gcnew System::Windows::Controls::Button();
    
    }
    


  • Also, nochmals etwas ausführlicher:
    Wenn Du eine bestehende Win32-Anwendung hast, dann musst Du folgendes tun:

    Ersetze den Code:

    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
    

    durch

    #pragma managed(push, off)
    EXTERN_C IMAGE_DOS_HEADER __ImageBase;
    HINSTANCE GetHInstance()
    {
      HINSTANCE hInstance = (HINSTANCE) &__ImageBase;
      return hInstance;
    }
    #pragma managed(pop)
    
    #pragma comment(linker, "/entry:main")
    [System::STAThreadAttribute]
    int main(array<System::String ^> ^args)
    {
    	//UNREFERENCED_PARAMETER(hPrevInstance);
    	//UNREFERENCED_PARAMETER(lpCmdLine);
    
      HINSTANCE hInstance = GetHInstance();
      STARTUPINFO si;
      ZeroMemory(&si, sizeof(STARTUPINFO));
      si.cb = sizeof(STARTUPINFO);
      GetStartupInfo(&si);
      int nCmdShow = SW_SHOW;
      if (si.dwFlags & STARTF_USESHOWWINDOW)
        int nCmdShow = si.wShowWindow;
    

    Dann geht es 😉



  • Das probier ich nochmal! Danke!


Anmelden zum Antworten