好的,这是一段针对你提供的易语言代码的描述,适合用于论坛发帖,并明确指出了代码存在的问题和无法运行的状态:
帖子标题: 【求助/讨论】尝试将 DirectComposition C++ ApplyEffects 示例翻译为易语言 (代码无法运行)
帖子内容:
大家好,
我正在尝试学习和使用 Windows 的 DirectComposition API,并将微软官方的 C++ 示例 ApplyEffects
翻译成易语言。
这个示例的预期功能是:
- 在窗口中显示一张图片 (来自资源)。
- 当鼠标悬停在图片上时,图片完全不透明 (
OPAQUE
)。
- 当鼠标移出图片时,图片变为半透明 (
TRANSPARENT
)。
- 当用户点击图片时,图片会执行一个 3D 旋转动画。
我根据 C++ 示例的逻辑,编写了以下的易语言代码。代码结构大致如下:
DemoApp
类: 封装了应用程序的主要逻辑,包括窗口句柄、Direct3D/DirectComposition 设备指针、Visual 指针等。
- 初始化 (
Initialize
, InitializeDirectCompositionDevice
, CreateResources
): 创建 D3D11 设备、DXGI 设备、DirectComposition 设备和窗口目标,并加载 GDI 位图资源。
- 消息循环 (
RunMessageLoop
): 标准的 Windows 消息处理循环。
WndProc
: 窗口过程函数,处理 WM_PAINT
, WM_MOUSEMOVE
, WM_LBUTTONDOWN
, WM_DESTROY
等消息。
OnPaint
: 在 WM_PAINT
中创建 IDCompositionVisual
,调用 MyCreateGDIRenderedDCompSurface
将 GDI 位图绘制到 Surface 上,设置 Visual 的内容、位置和初始透明度,并提交显示。
OnMouseMove
: 根据鼠标坐标判断是否在图片区域内,调用 SetVisualOpacity
改变透明度。
OnClientClick
: 判断点击位置,如果在图片内则调用 RotateVisual
。
SetVisualOpacity
: 使用 IDCompositionEffectGroup
来设置 IDCompositionVisual
的透明度属性。
RotateVisual
: 使用 IDCompositionRotateTransform3D
和 IDCompositionAnimation
来实现 Visual 的 3D 旋转动画。
MyCreateGDIRenderedDCompSurface
: (问题所在) 尝试创建一个 DirectComposition Surface,获取其 DC,然后使用 GDI 的 BitBlt
将加载的 HBITMAP 绘制上去。
LoadResourceGDIBitmap
: 从资源加载 HBITMAP。
SafeRelease
: 用于安全释放 COM 接口的辅助函数。
.版本 2
.支持库 spec
.支持库 shellEx ' 可能需要数学函数和 GuidFromString
' --- 常量定义 ---
#常量 OFFSET_X, 整数型, 20
#常量 OFFSET_Y, 整数型, 20
#常量 TRANSPARENT, 小数型, 0.5 ' C++ 是 float,易语言用小数型
#常量 OPAQUE, 小数型, 1.0
#常量 IDB_PENGUINS, 整数型, 101 ' 假设资源 ID
' --- 全局子程序:安全释放 COM 对象 ---
.子程序 SafeRelease, , , 安全释放 COM 接口指针
.参数 pInterface, 整数型, 参考, COM 接口指针变量
.如果真 (pInterface ≠ 0)
IUnknown_Release (pInterface) ' 依赖 IUnknown_Release 包装器
pInterface = 0
.如果真结束
' --- 主程序类 ---
.程序集 DemoApp_ApplyEffects
.程序集变量 m_hwnd, 整数型
.程序集变量 m_hBitmap, 整数型
.程序集变量 m_pD3D11Device, 整数型
.程序集变量 m_pDevice, 整数型 ' DComp Device
.程序集变量 m_pCompTarget, 整数型
.程序集变量 m_pVisual, 整数型
.程序集变量 m_bitmapWidth, 整数型
.程序集变量 m_bitmapHeight, 整数型
.程序集变量 m_fOverImage, 逻辑型 ' 鼠标悬停标志
' (此处省略 _初始化, _销毁, Initialize, InitializeDirectCompositionDevice, CreateResources, DiscardResources, RunMessageLoop 的详细代码 - 与帖子中提供的代码一致)
' ...
.子程序 OnPaint, 整数型, 公开
.局部变量 hr, 整数型
.局部变量 pSurface, 整数型
' (此处省略 OnPaint 的详细代码 - 与帖子中提供的代码一致)
' ...
返回 (hr)
.子程序 OnClientClick, 整数型, 公开, 处理 WM_LBUTTONDOWN 消息
.参数 xPos, 整数型, , 鼠标 X 坐标
.参数 yPos, 整数型, , 鼠标 Y 坐标
.局部变量 hr, 整数型
' (此处省略 OnClientClick 的详细代码 - 与帖子中提供的代码一致)
' ...
返回 (hr)
.子程序 OnMouseMove, 整数型, 公开, 处理 WM_MOUSEMOVE 消息
.参数 xPos, 整数型, , 鼠标 X 坐标
.参数 yPos, 整数型, , 鼠标 Y 坐标
.局部变量 hr, 整数型
.局部变量 isOver, 逻辑型
' (此处省略 OnMouseMove 的详细代码 - 与帖子中提供的代码一致)
' ...
返回 (hr)
.子程序 RotateVisual, 整数型, 公开, 应用 3D 旋转动画到 Visual
.参数 pVisual, 整数型, , 要旋转的 Visual 指针
.参数 degrees, 小数型, , 旋转角度 ' C++ 是 float
.局部变量 hr, 整数型
.局部变量 pAnimation, 整数型
.局部变量 pRotate3D, 整数型
.局部变量 pEffectGroup, 整数型
' (此处省略 RotateVisual 的详细代码 - 与帖子中提供的代码一致)
' ...
返回 (hr)
.子程序 SetVisualOpacity, 整数型, 公开
.参数 pVisual, 整数型
.参数 opacity, 小数型 ' C++ 是 float
.局部变量 pEffectGroup, 整数型
.局部变量 hr, 整数型
' (此处省略 SetVisualOpacity 的详细代码 - 与帖子中提供的代码一致)
' ...
返回 (hr)
.子程序 MyCreateGDIRenderedDCompSurface, 整数型, 公开
.参数 hBitmap, 整数型
.参数 ppSurface, 整数型, 参考
.局部变量 hr
.局部变量 bmpSize
.局部变量 hBitmapOld
.局部变量 hSurfaceDC
.局部变量 hBitmapDC
.局部变量 pDXGISurface
.局部变量 pDCSurface
.局部变量 pointOffset, POINTAPI
.局部变量 bmp, BITMAP
.局部变量 _uuidOf, 字节集
' (此处省略 MyCreateGDIRenderedDCompSurface 的详细代码 - 与帖子中提供的代码一致)
' --- 问题点在这里 ---
.如果真 (SUCCEEDED (hr))
' !!! 此调用失败,返回 E_INVALIDARG (0x80070057) !!!
hr = IDXGISurface1_GetDC (pDXGISurface, 0, hSurfaceDC)
.如果真结束
' ... 后续 GDI 操作也因此无法执行 ...
返回 (hr)
.子程序 LoadResourceGDIBitmap, 整数型, 公开
.参数 resourceID, 整数型 ' 修改为接受整数 ID
.参数 hbmp, 整数型, 参考
.局部变量 hInst, 整数型
hInst = GetModuleHandleW(0)
hbmp = LoadImageW (hInst, resourceID, #IMAGE_BITMAP, 0, 0, #LR_DEFAULTCOLOR)
返回 (选择 (hbmp ≠ 0, #S_OK, #E_FAIL))
' --- 窗口过程 和 主程序入口 ---
' (此处省略 WndProc 和 __启动窗口_创建完毕 的详细代码 - 使用全局变量 g_pCurrentDemoApp 的版本)
' ...
!!! 重要警告:此代码目前无法正常运行 !!!
主要问题在于 MyCreateGDIRenderedDCompSurface
子程序。 在尝试将 GDI 位图绘制到 DirectComposition Surface 时,调用 IDXGISurface1_GetDC
这一步会失败,返回错误码 0x80070057 (E_INVALIDARG)
。
根据之前的讨论和分析,这极有可能是因为通过 IDCompositionDevice::CreateSurface
创建的 Surface 默认不支持 GDI 设备上下文 (DC) 的获取。DirectComposition 的 Surface 主要设计用于 Direct2D 或 Direct3D 渲染。直接在其上使用 GetDC
并进行 GDI 操作(如 BitBlt
)是不被支持的。
其他潜在问题:
- API 包装器: 代码的正确运行依赖于所有
IDComposition*
, IDXGI*
, ID3D11*
等接口方法都有对应的、功能正确的易语言包装子程序。如果这些包装器有误,代码也会失败。
- 动画函数参数:
RotateVisual
中调用 IDCompositionAnimation_AddCubic
和 End
的参数是基于对 C++ 示例的理解,可能与实际易语言包装器的参数不完全匹配,需要核对。
- 窗口过程访问类: 使用了全局变量
g_pCurrentDemoApp
来在 WndProc
中访问类实例,这是一个可行的变通方法,但在更复杂的应用中可能不是最佳实践。
发帖目的:
我将这段(有问题的)代码发出来,主要是希望:
- 寻求帮助: 是否有大佬知道在易语言中,如何正确地将一个 GDI 位图(HBITMAP)的内容动态更新到
IDCompositionSurface
上?(正确的方法很可能是使用 Direct2D 进行绘制,而不是 GetDC/BitBlt)。
- 讨论交流: 分享这个不成功的尝试,希望能和大家讨论在易语言中使用 DirectComposition 的正确姿势和常见陷阱。
- 学习记录: 记录下这个失败的尝试,以便日后参考。
如果大家对如何修复 MyCreateGDIRenderedDCompSurface
中的 GetDC
问题(或者更好的替代方案,如 Direct2D)有任何建议或经验,恳请不吝赐教!感谢!
使用说明:
- 你可以将上述描述和代码片段复制粘贴到论坛帖子中。
- 代码部分可以根据需要进行折叠或简化,但务必保留核心逻辑和问题点的说明。
- 记得替换
#IDB_PENGUINS
为你实际使用的位图资源 ID。
- 确保你提到的易语言包装器(如
IUnknown_Release
, IDCompositionDevice_CreateVisual
等)是你项目中实际使用的名称。