AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题

问题[winapi](coding)

Martin Hope
gene b.
Asked: 2025-04-25 23:17:57 +0800 CST

Win32 API SHFormatDateTime 函数在前面添加不常见的特殊字符

  • 2

出于某种原因,当我使用 Win32 APISHFormatDateTime函数获取文件的修改日期时,无论带有什么标志,它都会在前面添加一些奇怪的特殊字符,如下所示。

这发生在循环文件()的上下文中WIN32_FIND_DATAA findData,这可能与此相关,也可能不相关。

简单的 ANSI 版本 - SHFormatDateTimeA:

hFind = FindFirstFileA(full_path.c_str(), &findData);
while (FindNextFileA(hFind, &findData) != 0) {   

    char datebuf[80];
    DWORD flags = FDTF_DEFAULT;
    SHFormatDateTimeA(&findData.ftLastWriteTime, &flags, datebuf, 80);
    std::string lastModifiedDateStr = std::string(datebuf);

输出:?4/?25/?2025 ??9:44 AM

Unicode 版本 - SHFormatDateTimeW:

    wchar_t datebuf[80];
    DWORD flags = FDTF_DEFAULT;
    SHFormatDateTimeW(&findData.ftLastWriteTime, &flags, datebuf, 80);
    std::wstring lastModifiedDateStr = std::wstring(datebuf);

输出:u+200E‎ 4 / ‎u+200E 25 / ‎u+200E 2025 u+200F u+200E ‏‎9 : 44 AM

因此,无论使用 ANSI 还是 Unicode,该函数SHFormatDateTime都会在每个部分前添加一些奇怪的字符。我尝试了各种标志,例如FDTF_DEFAULT、FDTF_SHORTDATE,甚至NULL。其他 Shell WIn32 API 函数没有这个问题。

winapi
  • 1 个回答
  • 30 Views
Martin Hope
gene b.
Asked: 2025-04-21 07:25:30 +0800 CST

调用 DeleteObject() 后验证无效句柄

  • 4

Win32 中有许多不同的句柄类型,例如、HWND等等。我的理解是,我有责任在最后用 来关闭它们。此外,某些句柄类型(例如)具有附加函数(例如),因此我也必须调用它们。HFONTHIMAGELISTDeleteObject()HIMAGELISTImageList_Destroy

我想验证一下清理后句柄是否失效。假设我有

HWND hWnd;
HFONT hFont;
HIMAGELIST hImageList;

//...
// On Exit:
case WM_DESTROY:
    DeleteObject(hWnd);
    DeleteObject(hFont);
    ImageList_Destroy(hImageList);
    DeleteObject(hImageList);

在VS调试器中,我看到这些删除操作后句柄的值没有变化。删除前后都完全相同:

hWnd        0x00000000e806b2
hFont       0xfffffffe20a140
hImageList  0x000001c76a943e

它应该改变吗?我怎么知道我清理了这些句柄?

winapi
  • 2 个回答
  • 76 Views
Martin Hope
gene b.
Asked: 2025-03-29 09:17:09 +0800 CST

在工具栏的开头添加并定位 ComboBox 控件,后面跟有其他按钮

  • 6

在我的 Win32 应用程序中,我有一个工具栏,它需要有一个主组合框下拉菜单,从左侧开始跨越工具栏的 70%,然后是任何附加按钮(例如在本例中为剪切/复制/粘贴) - 可能在一个小的分隔符之后。

[--------------------Dropdown-------------------V] | [Cut][Copy][Paste]

在此代码中,我首先为工具栏创建子 ComboBox 控件,并使其具有 Toolbar Rect 宽度的 70% setWindowPos,然后继续使用常规按钮。但是,没有 ComboBox,只显示了 3 个按钮。

我想我必须SetWindowPos对每个按钮都这样做,但我希望它们自然流动而不需要明确地定位它们,就像没有组合框一样。

void CreateToolbar1(HWND hWndParent)
{
    // Declare and initialize local constants.
    const int ImageListID = 0;
    const int numButtons = 3;
    const int bitmapSize = 16;

    const DWORD buttonStyles = BTNS_AUTOSIZE;

    // Create the toolbar.
    hWndToolbar1 = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
        WS_CHILD | TBSTYLE_WRAPABLE | TBSTYLE_FLAT, 0, 0, 0, 0,
        hWndParent, NULL, GetModuleHandle(NULL), NULL);

    // Obtain toolbar's rectangle coordinates
    RECT rectToolbar1;
    SendMessage(hWndToolbar1, TB_GETITEMRECT, (WPARAM)0, (LPARAM)&rectToolbar1);

    // Add ComboBox control to toolbar, should take up 70% of the width
    HWND hWndDropdown = CreateWindowEx(WS_EX_CLIENTEDGE, WC_COMBOBOXEX, NULL, WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, 0, 0, 100, 35, hWndToolbar1, NULL, GetModuleHandle(NULL), NULL);
    SetWindowPos(hWndDropdown, NULL, rectToolbar1.left, rectToolbar1.top, 0.7 * (rectToolbar1.right - rectToolbar1.left), rectToolbar1.bottom - rectToolbar1.top, SWP_SHOWWINDOW);

    // Add 3 regular buttons afterwards (Cut/Copy/Paste)
    // ---
    // Create the image list.
    g_hImageList = ImageList_Create(bitmapSize, bitmapSize,   // Dimensions of individual bitmaps.
        ILC_COLOR16 | ILC_MASK,   // Ensures transparent background.
        numButtons, 0);

    // Set the image list.
    SendMessage(hWndToolbar1, TB_SETIMAGELIST,
        (WPARAM)ImageListID,
        (LPARAM)g_hImageList);

    // Load the button images.
    SendMessage(hWndToolbar1, TB_LOADIMAGES,
        (WPARAM)IDB_STD_SMALL_COLOR,
        (LPARAM)HINST_COMMCTRL);

    // Initialize buttons Cut/Copy/Paste
    TBBUTTON tbButtons[numButtons] =
    {
        { MAKELONG(STD_CUT,  ImageListID), IDM_CUT,  TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Cut" },
        { MAKELONG(STD_COPY, ImageListID), IDM_COPY, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Copy"},
        { MAKELONG(STD_PASTE, ImageListID), IDM_PASTE, 0,               buttonStyles, {0}, 0, (INT_PTR)L"Paste"}
    };

    // Add buttons.
    SendMessage(hWndToolbar1, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    SendMessage(hWndToolbar1, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);

    // Resize the toolbar, and then show it.
    SendMessage(hWndToolbar1, TB_AUTOSIZE, 0, 0);
    ShowWindow(hWndToolbar1, TRUE);

}
winapi
  • 1 个回答
  • 42 Views
Martin Hope
Sonicsmooth
Asked: 2025-02-12 13:01:04 +0800 CST

在长时间运行的过程中,窗口变得无响应并且因移动尝试而冻结

  • 4

所讨论的语言是 Nim,使用 wNim 库,但实际上问题是关于 win32 api,因为 wNim 是 Win32 gui 的一个非常轻量级的包装器。

我有一个单线程程序。当用户单击按钮时,它会启动一个长时间运行的计算。在每个第 n 个周期,计算偶尔会用 更新窗口InvalidateRect,然后是UpdateWindow。WM_PAINT处理程序会立即在屏幕上绘制一些内容。有时我会引入一个sleep几毫秒的 ,认为这会让系统WM_xxx消息有时间赶上。

这通常可以正常工作。我可以在客户端区域以图形方式查看计算进度。

但是,当我尝试在更新期间移动窗口时(无论有没有sleep),它不仅不响应移动(如果sleep(...)省略,这是可以理解的),而且图形onPaint完全停止,窗口变成程序死机时 Windows 呈现的幽灵白色。通常,命令行中的调试输出会继续。通常(但并非总是),命令行输出会停止,然后出现 Windows 对话框,告诉我程序崩溃了。我随时都可以在命令行中按 ctrl-c 并恢复正常。有人能解释一下是什么特定的事件序列和处理不当的消息导致一切都惨遭失败吗?

下面是伪代码。有没有一种适当的方法可以让长时间运行的前台计算更新客户端区域,同时响应其他用户事件,而无需多线程?或者多线程是这里最好的选择?我怀疑我的sleep(...)调用是将一些周期返回到消息传递机制的地方。

伪代码:

proc onButton():
    while(stuffNotDone):
        doExpensiveStuff()
        InvalidateRect(false) # <-- Win32 call
        UpdateWindow()        # <-- Win32 call
        Sleep(10)             # <-- Win32 call (optional)

proc onPaint(event):
    # Responds to WM_PAINT
    var dc = PaintDC(...)           # <-- leads to Win32 BeginPaint
    dc.blit(...)                    # <-- leads to Win32 call
    SendMessage(hwnd, WM_APP+3,0,0) # <-- Win32 call to clear data elsewhere
    
winapi
  • 2 个回答
  • 42 Views
Martin Hope
Tom
Asked: 2025-01-17 21:41:11 +0800 CST

单击按钮后,其周边保持突出显示。我想知道如何取消此

  • 7

我在对话框页面上有很多按钮。有一次,我创建了其中一个按钮,其边缘突出显示。查看此内容后,我确定按下按钮后也会发生同样的事情。释放按钮后,边缘仍会略微突出显示。所有按钮都是使用 DIALOGEX 在 .rc 文件中创建的。

使用如下代码创建了 50 多个按钮:

DEFPUSHBUTTON "  P0100 MASS AIR FLOW SENSOR CIRCUIT INSUFFICIENT ACTIVITY", IDC_M17_P0100, 5, 45, 300, 14, BS_LEFT, WS_EX_CLIENTEDGE

我重叠按钮并使用以下代码启用/禁用它们:

ShowWindow(GetDlgItem(hDlg, IDC_M17_P0100), nShow);

一旦创建并变得更好,按下按钮后我希望它们保持不突出显示。我一直在寻找一种风格/扩展风格,但一无所获。

编辑:以下是其中一个对话片段

    IDD_MODE_$17 DIALOGEX 0, 0, 500, 500
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU //| DS_CONTROL | WS_THICKFRAME  | WS_VSCROLL
//EXSTYLE WS_EX_WINDOWEDGE
CAPTION "Mode $17 Diagnostics"
FONT 10, "MS Shell Dlg"
BEGIN
//SCROLLBAR IDC_VSCROLLBAR, 570, 0, 10, 300, SBS_VERT
LTEXT           "Mode $17: Request status of diagnostic trouble codes (DTC)", IDC_STATIC, 5, 5, 200, 10, SS_NOPREFIX

DEFPUSHBUTTON "  P0100 MASS AIR FLOW SENSOR CIRCUIT INSUFFICIENT ACTIVITY", IDC_M17_P0100, 5, 45, 300, 14, BS_LEFT, WS_EX_CLIENTEDGE
...
DEFPUSHBUTTON "  P1886 3-2 SHIFT SOLENOID VALVE CIRCUIT", IDC_M17_P1886, 5, 285, 300, 14, BS_LEFT, WS_EX_CLIENTEDGE

LTEXT           "", IDS_RESULT, 310, 45, 200, 300, SS_NOPREFIX | BS_LEFT, WS_EX_CLIENTEDGE

END

Jabberwocky 关于 DEFPUSHBUTTON 与 PUSHBUTTON 的评论是正确的。我理解了两者的区别,谢谢。Raymond 关于只有一个默认值的评论我现在确信也是正确的,但不会影响结果。似乎最后生成的 DEFPUSHBUTTON 只是成为默认值。这不是我想要的,所以我把所有都改成了 PUSHBUTTON 。但突出显示仍然存在。有没有我可以添加的样式来使按钮不突出显示?有些方法超出了我的理解范围...

突出显示的按钮是“P1886 2-3 换档...”

问题不在于代码,而在于理解为什么标记为 P1886 的按钮略微突出显示。如果我知道为什么会这样,也许我可以发送一条消息来重置参数。目前应用程序运行正常,但不理解突出显示以及如何使用它很困难。我试过调整焦点和突出显示。我不确定发布什么代码可以帮助更好地显示问题。

winapi
  • 1 个回答
  • 67 Views
Martin Hope
unicus
Asked: 2024-12-21 20:04:09 +0800 CST

如何创建与 direct3d12 兼容的交换链?

  • 6

我尝试为 d3d12 创建一个交换链,但发现不能对 d3d11 使用相同的函数,但即使正确的函数对我来说也不起作用。

    COM<IDXGISwapChain4> swapchain(NULL); {
        COM<IDXGISwapChain1> temp(NULL);
        LOG(factory->CreateSwapChainForHwnd(queue.ptr, hwnd, (DXGI_SWAP_CHAIN_DESC1[]){{
            .Width = 1000, .Height = 600,
            .Format = DXGI_FORMAT_R8G8B8A8_UNORM,
            .SampleDesc = (DXGI_SAMPLE_DESC){
                .Count = 1,
                .Quality = 0,
            },
            .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
            .BufferCount = 2,
            .SwapEffect = DXGI_SWAP_EFFECT_DISCARD,
            .Flags = 0
        }}, NULL, NULL, &temp.ptr)); d3dmsg();
        if(temp.ptr) LOG(temp->QueryInterface(IID_PPV_ARGS(&swapchain.ptr)));
    }

我确实使用 _com_error 将错误写入控制台,甚至使用 d3d12debug 来启用调试层。

hresult 的错误消息显示The application made a call that is invalid. Either the parameters of the call or the state of some object was incorrect. Enable the D3D debug layer in order to see details via debug messages.,但我不明白我到底做错了什么,我也尝试使用正确的结构,但也没有用。

我自己正在处理 d3d 调试消息,但它还没有将任何内容打印到控制台,我不知道是否也失败了。

auto d3dmsg = [&info_queue](){
        UINT64 messageCount = info_queue->GetNumStoredMessages();
        for (UINT64 i = 0; i < messageCount; ++i) {
            SIZE_T messageLength = 0;
            info_queue->GetMessage(i, nullptr, &messageLength);

            // Allocate space for the message
            D3D12_MESSAGE* message = (D3D12_MESSAGE*)malloc(messageLength);
            if (message != nullptr) {
                // Get the message
                info_queue->GetMessage(i, message, &messageLength);

                if (message->Severity == D3D12_MESSAGE_SEVERITY_ERROR|D3D12_MESSAGE_SEVERITY_WARNING) {
                    printf("D3D12 Error: %s\n", message->pDescription);
                }

                // Free the allocated memory
                free(message);
            }
        }
        
    }; 

我想了解我做错了什么。我只是想写一个 hello_triangle。

winapi
  • 1 个回答
  • 60 Views
Martin Hope
Michael Chourdakis
Asked: 2024-12-13 20:02:37 +0800 CST

使用 Vds 格式化 VHD 磁盘(或任何其他磁盘)

  • 5
  1. 我正在使用CreateVirtualDisk创建虚拟驱动器。
  2. 我正在用AttachVirtualDisk连接它。
  3. 我使用IOCTL_DISK_CREATE_DISK为单个 GPT 分区进行初始化。
  4. 我使用IOCTL_DISK_SET_DRIVE_LAYOUT_EX创建一个分区。

现在我必须用 NTFS 格式化它。我可以使用此问题中描述的 FormatEx,但这需要一个挂载点。

我尝试使用VDS。我得到了一个 IVdsServiceLoader ,我查询了 VDS_QUERY_VIRTUALDISK_PROVIDERS ,发现我的附加磁盘是 IVdsDisk。

但是我现在还不知道如何格式化它。我看到 IVdsAdvancedDisk 有格式化选项,但我不知道如何获取此界面。

还有其他选择吗?我发现,我无法使用 DeviceIoControl 进行格式化。

winapi
  • 1 个回答
  • 37 Views
Martin Hope
Mapeman
Asked: 2024-11-30 23:38:02 +0800 CST

使用 Ownerdraw 键访问菜单栏

  • 5

由于我使用 owndraw 作为菜单栏,因此按键访问不再起作用。没有 owndraw 时,Alt+F 可用于项目“&File”,使用 owndraw 时则没有任何反应。这里缺少什么?当我处理 WM_MENUSELECT 时,wParam 不提供任何信息。

菜单创建:

HMENU hm;
HMENU winmenu = CreateMenu ();

MENUINFO mi;
mi.cbSize = sizeof (mi);
mi.fMask = MIM_BACKGROUND;
mi.hbrBack = (HBRUSH)CreateSolidBrush (RGB (70, 70, 70));
SetMenuInfo (winmenu, &mi);
UINT barFlags = MF_POPUP|MF_OWNERDRAW;

hm = CreatePopupMenu ();
AppendMenuW (winmenu, barFlags, (UINT)hm, L"&File");
AppendMenuW (hm, MF_STRING, IDM_OPENFILE, L"&Open");
...

SetMenu (hwnd, winmenu);
DrawMenuBar (hwnd);

业主提款处理:

case WM_MEASUREITEM:
{
    LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT)lParam;
    HDC hdc = GetDC (hwnd);
    SIZE size;
    GetTextExtentPoint32W (hdc, (PWCHAR)lpmi->itemData, wcslen ((PWCHAR)lpmi->itemData), &size);
    lpmi->itemWidth = size.cx;
    lpmi->itemHeight = size.cy;
    ReleaseDC (hwnd, hdc);
    break;
}
case WM_DRAWITEM:
{
    LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
    if (lpdis->CtlType == ODT_MENU)
    {
        HDC hdc = lpdis->hDC;
        HPEN oldPen = (HPEN) SelectObject(hdc, GetStockObject (DC_PEN));
        HBRUSH oldBrush = (HBRUSH) SelectObject(hdc, GetStockObject (DC_BRUSH));
        SetBkMode (hdc, TRANSPARENT);

        if ((lpdis->itemState & ODS_HOTLIGHT) || (lpdis->itemState & ODS_SELECTED))
        {
            SetDCPenColor (hdc, RGB (70, 20, 20));
            SetDCBrushColor (hdc, RGB (70, 20, 20));
            SetTextColor (hdc, RGB (255, 255, 255));
        }
        else
        {
            SetDCPenColor (hdc, RGB (70, 70, 70));
            SetDCBrushColor (hdc, RGB (70, 70, 70));
            SetTextColor (hdc, RGB (255, 255, 255));
        }
        Rectangle (hdc, lpdis->rcItem.left, lpdis->rcItem.top, lpdis->rcItem.right, lpdis->rcItem.bottom);
        DrawTextW (hdc, (PWCHAR)lpdis->itemData, -1, &lpdis->rcItem,
            ((lpdis->itemState & ODS_NOACCEL) ? DT_HIDEPREFIX : 0)
            |DT_SINGLELINE|DT_CENTER|DT_VCENTER);

        SelectObject (hdc, oldPen);
        SelectObject (hdc, oldBrush);
    }
    break;
}
winapi
  • 1 个回答
  • 21 Views
Martin Hope
user19250735
Asked: 2024-11-15 06:03:21 +0800 CST

coder.ptr 为 nullptr CreateDesktopWindowTarget - IDesktopWindowTarget

  • 7

在 C++ 中,我想加载图像,并使用 winrt 合成将其渲染到 win32 窗口。我只是想为我的其他应用程序构建一个简单的测试平台来测试 2dtexture 合成。

到目前为止,我已经尝试了很多实现方法。

void CreateDesktopWindowTarget(HWND window)
{
    namespace abi = ABI::Windows::UI::Composition::Desktop;

    auto interop = m_compositor.as<abi::ICompositorDesktopInterop>();
    DesktopWindowTarget target{ nullptr };
    check_hresult(interop->CreateDesktopWindowTarget(window, false, reinterpret_cast<abi::IDesktopWindowTarget**>(put_abi(target))));
    m_target = target;
}

他们的大多数示例和示例代码都是这样的。这里失败了:

    check_hresult(interop->CreateDesktopWindowTarget(window, false, reinterpret_cast<abi::IDesktopWindowTarget**>(put_abi(target))));

和:

C++: Exception thrown: read access violation. decoder.**ptr** was nullptr. (decoder.ptr was nullptr.)

我不知道或不理解这种 abi 类型反射在做什么。很难调试。失败只是深奥难懂。

这个临时文件就是我所在的位置:

#define NOMINMAX
#include <windows.h>
#include <windows.ui.composition.h>
#include <windows.ui.composition.desktop.h>
#include <windows.ui.composition.interop.h>
#include <unknwn.h>       // For IUnknown and related COM interfaces
#include <activation.h>   // For IActivationFactory
#include <roapi.h>        // For RoInitialize, RoUninitialize, RoGetActivationFactory
#include <wrl.h>          // For Microsoft::WRL::ComPtr
#include <d3d11.h>
#include <dxgi1_2.h>
#include <dxgidebug.h>
#include <cstdio>
#include <combaseapi.h>

// Link necessary libraries
#pragma comment(lib, "runtimeobject.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxguid.lib")

#include <wrl/client.h> // For Microsoft::WRL::ComPtr

// WIL (Windows Implementation Library)
#include <wil/cppwinrt.h> // Needs to come before C++/WinRT headers
#include <wil/resource.h>
#include <wil/cppwinrt_helpers.h>
#include <wil/coroutine.h>

// C++/WinRT headers
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Foundation.Metadata.h>
#include <winrt/Windows.Graphics.Capture.h>
#include <winrt/Windows.Graphics.DirectX.h>
#include <winrt/Windows.Graphics.DirectX.Direct3D11.h>
#include <winrt/Windows.Graphics.Imaging.h>
#include <winrt/Windows.Security.Authorization.AppCapabilityAccess.h>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.Storage.Pickers.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.UI.h>
#include <winrt/Windows.UI.Composition.h>
#include <winrt/Windows.UI.Composition.Desktop.h>
#include <winrt/Windows.UI.Popups.h>
#include <winrt/Windows.Foundation.Numerics.h>
#include <winrt/Windows.UI.Composition.Interactions.h>

// STL headers
#include <atomic>
#include <memory>
#include <algorithm>
#include <unordered_set>
#include <vector>
#include <optional>
#include <future>
#include <mutex>

// D3D headers
#include <d3d11.h>
#include <d3d11_4.h>
#include <dxgi1_6.h>
#include <d2d1_3.h>
#include <wincodec.h>

// Helper headers
#include "ComPtr.hpp"
#include <robmikh.common/composition.interop.h>
#include <robmikh.common/composition.desktop.interop.h>
#include <robmikh.common/d3d11Helpers.h>
#include <robmikh.common/d3d11Helpers.desktop.h>
#include <robmikh.common/direct3d11.interop.h>
#include <robmikh.common/d2dHelpers.h>
#include <robmikh.common/capture.desktop.interop.h>
#include <robmikh.common/dispatcherqueue.desktop.interop.h>
#include <robmikh.common/stream.interop.h>
#include <robmikh.common/hwnd.interop.h>
#include <robmikh.common/ControlsHelper.h>



#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "windowscodecs.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "comctl32.lib")


using namespace winrt;

namespace winrt
{
    using namespace Windows::UI::Composition;
    using namespace Windows::UI::Composition::Desktop;
    using namespace Windows::Graphics::DirectX::Direct3D11;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Numerics;

    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Numerics;
    using namespace Windows::Graphics;
    using namespace Windows::Graphics::Capture;
    using namespace Windows::Graphics::DirectX;
    using namespace Windows::Graphics::DirectX::Direct3D11;
    using namespace Windows::System;
    using namespace Windows::UI;
    using namespace Windows::UI::Composition;
    using namespace Windows::System;
    using namespace Windows::UI::Composition::Desktop;
    using namespace Windows::Foundation::Numerics;
}

namespace util
{
    using namespace robmikh::common::uwp;
    using namespace robmikh::common::desktop;
}

winrt::Windows::UI::Composition::Compositor m_compositor{ nullptr };
winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget m_target{ nullptr };
winrt::Windows::UI::Composition::ContainerVisual m_root{ nullptr };
winrt::Windows::UI::Composition::SpriteVisual m_content{ nullptr };
winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{ nullptr };
winrt::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice m_device{ nullptr };
winrt::com_ptr<IDXGISwapChain1> m_swapChain{ nullptr };
winrt::com_ptr<ID3D11Device> m_d3dDevice{ nullptr };
winrt::com_ptr<ID3D11DeviceContext> m_d3dContext{ nullptr };
winrt::Windows::System::DispatcherQueueController m_dispatcherQueueController{ nullptr };


void CreateDesktopWindowTarget(HWND window)
{
    namespace abi = ABI::Windows::UI::Composition::Desktop;

    auto interop = m_compositor.as<abi::ICompositorDesktopInterop>();
    DesktopWindowTarget target{ nullptr };
    check_hresult(interop->CreateDesktopWindowTarget(window, false, reinterpret_cast<abi::IDesktopWindowTarget**>(put_abi(target))));
    m_target = target;
}

void CreateCompositionRoot()
{
    auto root = m_compositor.CreateContainerVisual();
    root.RelativeSizeAdjustment({ 1.0f, 1.0f });
    root.Offset({ 124, 12, 0 });
    m_target.Root(root);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_DESTROY)
    {
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

void EnsureDispatcherQueue()
{
    namespace abi = ABI::Windows::System;

    if (m_dispatcherQueueController == nullptr)
    {
        DispatcherQueueOptions options
        {
            sizeof(DispatcherQueueOptions), /* dwSize */
            DQTYPE_THREAD_CURRENT,          /* threadType */
            DQTAT_COM_ASTA                  /* apartmentType */
        };

        winrt::Windows::System::DispatcherQueueController controller{ nullptr };
        check_hresult(CreateDispatcherQueueController(options, reinterpret_cast<abi::IDispatcherQueueController**>(put_abi(controller))));
        m_dispatcherQueueController = controller;
    }
}

int main()
{
    winrt::init_apartment(winrt::apartment_type::multi_threaded);
    EnsureDispatcherQueue();
    auto m_compositor = winrt::Compositor();

    const wchar_t CLASS_NAME[] = L"FrameShowWindowClass";

    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpszClassName = CLASS_NAME;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&wc);

    DWORD style = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
    DWORD exStyle = 0;

    RECT rect = { 0, 0, 1024, 1024 };
    AdjustWindowRectEx(&rect, style, FALSE, exStyle);
    HWND hwnd = CreateWindowEx(
        exStyle,
        CLASS_NAME,
        L"Frame Show",
        style,
        CW_USEDEFAULT, CW_USEDEFAULT,
        rect.right - rect.left,
        rect.bottom - rect.top,
        NULL,
        NULL,
        wc.hInstance,
        NULL
    );

    if (!hwnd)
    {
        return -1;
    }

    ShowWindow(hwnd, SW_SHOW);

    const wchar_t CHILD_CLASS_NAME[] = L"ChildWindowClass";

    WNDCLASS child_wc = {};
    child_wc.lpfnWndProc = WindowProc; 
    child_wc.hInstance = GetModuleHandle(NULL);
    child_wc.lpszClassName = CHILD_CLASS_NAME;
    child_wc.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&child_wc);

    HWND hwndChild = CreateWindowEx(
        0,
        CHILD_CLASS_NAME,
        NULL,
        WS_CHILD | WS_VISIBLE,
        0, 0, 1024, 1024,
        hwnd,
        NULL,
        wc.hInstance,
        NULL
    );


    auto d3dDevice = util::CreateD3D11Device();
    auto dxgiDevice = d3dDevice.as<IDXGIDevice>();
    m_device = CreateDirect3DDevice(dxgiDevice.get());

    auto d2dFactory = util::CreateD2DFactory();
    auto d2dDevice = util::CreateD2DDevice(d2dFactory, d3dDevice);
    winrt::com_ptr<ID2D1DeviceContext> d2dContext;

    ComPtr<IWICImagingFactory> wicFactory;
    CoCreateInstance(
        CLSID_WICImagingFactory,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&wicFactory)
    );

    ComPtr<IWICBitmapDecoder> decoder;
    std::wstring imagePath = L"C:\\data\\train - Copy\\outpu21567151.bmp";
    wicFactory->CreateDecoderFromFilename(
        imagePath.c_str(),
        nullptr,
        GENERIC_READ,
        WICDecodeMetadataCacheOnLoad,
        &decoder
    );

    ComPtr<IWICBitmapFrameDecode> frame;
    decoder->GetFrame(0, &frame);

    ComPtr<IWICFormatConverter> converter;
    wicFactory->CreateFormatConverter(&converter);
    converter->Initialize(
        frame.Get(),
        GUID_WICPixelFormat32bppRGBA,
        WICBitmapDitherTypeNone,
        nullptr,
        0.f,
        WICBitmapPaletteTypeCustom
    );

    UINT width, height;
    converter->GetSize(&width, &height);
    UINT stride = width * 4;
    UINT imageSize = stride * height;
    std::unique_ptr<BYTE[]> pixels(new BYTE[imageSize]);
    converter->CopyPixels(NULL, stride, imageSize, pixels.get());

    D3D11_TEXTURE2D_DESC texDesc = {};
    texDesc.Width = 1024;
    texDesc.Height = 1024;
    texDesc.MipLevels = 1;
    texDesc.ArraySize = 1;
    texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    texDesc.SampleDesc.Count = 1;
    texDesc.Usage = D3D11_USAGE_DEFAULT;
    texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    texDesc.CPUAccessFlags = 0;
    texDesc.MiscFlags = 0;

    ComPtr<ID3D11Texture2D> texture;
    d3dDevice->CreateTexture2D(&texDesc, nullptr, &texture);
    d3dDevice->GetImmediateContext(m_d3dContext.put());
    m_d3dContext->UpdateSubresource(texture.Get(), 0, nullptr, pixels.get(), stride, 0);
    
    CreateDesktopWindowTarget(hwndChild);
    CreateCompositionRoot();
    auto compositionGraphicsDevice = util::CreateCompositionGraphicsDevice(m_compositor, d2dDevice.get());
    auto compositionSurface = util::CreateCompositionSurfaceForSwapChain(m_compositor, texture.Get());
    SpriteVisual spriteVisual = m_compositor.CreateSpriteVisual();
    CompositionSurfaceBrush surfaceBrush = m_compositor.CreateSurfaceBrush(compositionSurface);
    spriteVisual.Brush(surfaceBrush);
    spriteVisual.RelativeSizeAdjustment({ 1.0f, 1.0f });
    m_target.Root(spriteVisual);

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

这只是一个临时文件。但我应该能够让它工作。如果你知道,我必须有一个调度队列吗?使用屏幕截图,我只需初始化一个单线程单元。

winapi
  • 1 个回答
  • 17 Views
Martin Hope
LUN
Asked: 2024-10-05 02:26:08 +0800 CST

注册窗口类时是否应该初始化 WNDCLASSEX.hInstance?

  • 5

该WNDCLASSEX结构有一个hInstance字段。

我已经创建了一个 DLL,它将注册一个窗口类(WNDCLASSEX wcex)并使用此类创建一个窗口。

wcex.hInstance在调用之前不定义字段(将其归零)是否正确RegisterClassExW(&wcex)?

或者我应该定义它,在 DLL 加载时获取?

winapi
  • 1 个回答
  • 30 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve