diff --git a/build/cmake/tests/CMakeLists.txt b/build/cmake/tests/CMakeLists.txt index edf8bbf719..5a84433a09 100644 --- a/build/cmake/tests/CMakeLists.txt +++ b/build/cmake/tests/CMakeLists.txt @@ -11,3 +11,6 @@ add_subdirectory(base) add_subdirectory(drawing) add_subdirectory(gui) add_subdirectory(headers) +if(WIN32) + add_subdirectory(win32) +endif() diff --git a/build/cmake/tests/win32/CMakeLists.txt b/build/cmake/tests/win32/CMakeLists.txt new file mode 100644 index 0000000000..f810a8b314 --- /dev/null +++ b/build/cmake/tests/win32/CMakeLists.txt @@ -0,0 +1,22 @@ +############################################################################# +# Name: build/cmake/tests/win32/CMakeLists.txt +# Purpose: CMake file for win32 test +# Author: Maarten Bent +# Created: 2025-11-15 +# Copyright: (c) 2025 wxWidgets development team +# Licence: wxWindows licence +############################################################################# + +set(TEST_SRC + testwin32.cpp +) + +wx_add_test(test_win32_wide ${TEST_SRC}) +if(TARGET test_win32_wide) + target_compile_definitions(test_win32_wide PRIVATE UNICODE _UNICODE) +endif() + +wx_add_test(test_win32_ansi ${TEST_SRC}) +if(TARGET test_win32_ansi) + target_compile_definitions(test_win32_ansi PRIVATE _SBCS) +endif() diff --git a/tests/testwin32.cpp b/tests/testwin32.cpp new file mode 100644 index 0000000000..e906fa06ff --- /dev/null +++ b/tests/testwin32.cpp @@ -0,0 +1,118 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: tests/testwin32.cpp +// Purpose: Test including Windows headers before wxWidgets headers +// Author: Maarten Bent +// Created: 2025-11-15 +// Copyright: (c) 2025 wxWidgets development team +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WIN32 + #error This is a Windows/win32 specific test +#endif + +// When including Windows headers before wx headers, the functions declared +// in wx/msw/winundef.h need to match the ANSI/WIDE variant in the Windows +// headers. By default the WIDE variant is declared, but if ANSI Windows is +// used, define wxNO_WIN32_W. +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#ifndef UNICODE + #define wxNO_WIN32_W +#endif + +#include "wx/wxprec.h" + +// include all headers, so incorrect usage of ANSI/WIDE win32 API in public +// headers is detected +#include "allheaders.h" + +#ifdef wxHAS_NATIVE_WINDOW + +class NativeWindow : public wxNativeWindow +{ +public: + explicit NativeWindow(wxWindow* parent) + : wxNativeWindow() + { + const wxSize size = FromDIP(wxSize(140, 30)); + + HWND hwnd = ::CreateWindow + ( + TEXT("BUTTON"), + TEXT("Press me to do it"), + WS_CHILD | WS_VISIBLE | BS_SPLITBUTTON, + 0, 0, size.x, size.y, + (HWND)parent->GetHWND(), 0, nullptr, nullptr + ); + if ( !hwnd ) + { + wxLogError("Creating split button failed."); + return; + } + + (void)Create(parent, wxID_ANY, hwnd); + } + + virtual ~NativeWindow() + { + Disown(); + } + +protected: + virtual bool + MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) override + { + const NMHDR* hdr = reinterpret_cast(lParam); + if ( hdr->code != BCN_DROPDOWN ) + return wxNativeWindow::MSWOnNotify(idCtrl, lParam, result); + + const NMBCDROPDOWN* dd = reinterpret_cast(lParam); + + wxMenu menu; + menu.Append(wxID_NEW); + menu.AppendSeparator(); + menu.Append(wxID_ABOUT); + PopupMenu(&menu, wxPoint(dd->rcButton.right, dd->rcButton.bottom)); + + return true; + } +}; + +#endif // wxHAS_NATIVE_WINDOW + +class MyFrame : public wxFrame +{ +public: + MyFrame(const wxString& title) + : wxFrame(nullptr, wxID_ANY, title) + { + wxSizer* m_sizerCtrl = new wxBoxSizer(wxHORIZONTAL); +#ifdef wxHAS_NATIVE_WINDOW + wxNativeWindow* m_nativeWindow = new NativeWindow(this); + m_sizerCtrl->Add(m_nativeWindow, wxSizerFlags(1).Expand().Border()); +#endif + SetSizer(m_sizerCtrl); + + CallAfter([&]() { Close(true); }); + } + +}; + +class MyApp : public wxApp +{ +public: + virtual bool OnInit() override + { + if (!wxApp::OnInit()) + return false; + + MyFrame* frame = new MyFrame("win32 test"); + frame->Show(true); + return true; + } +}; + +wxIMPLEMENT_APP(MyApp);