小编Dav*_*vid的帖子

是什么解释了这个奇怪的PeekMessage行为(尝试处理完整的消​​息队列,过滤特定的消息)?

我们的应用程序充当COM服务器,其中所有自动化都发生在单个STA公寓内(在应用程序的主线程中),并且一些进行冗长(> 10分钟)调用的VBS脚本失败,并显示错误"系统调用失败(80010100)" .一些研究(,,)表明这可能是由消息队列填满引起的,因此当COM尝试调用下一个方法时,它无法进行.

如果它很重要,该应用程序是使用Embarcadero RAD Studio 2010开发的(主要是C++,对于某些COM类的Delphi.)

我想我会在漫长的COM方法调用结束时检查线程的消息队列(即,在它返回之前),通过使用GetQueueStatus和查看它包含的内容PeekMessage.虽然看起来队列已经满了,但我看到了一些奇怪的行为,我无法弄清楚为什么PeekMessage它的行为方式,以及为什么队列已满 - 即它充满了什么.

前面稍微冗长的解释:

测试线程的消息队列已满

像这样的代码:

int iMessages = 0;
DWORD dwThreadId = GetCurrentThreadId();
while (::PostThreadMessage(dwThreadId, WM_USER, 0, 0)) {
  iMessages++;
}
if (GetLastError() == ERROR_NOT_ENOUGH_QUOTA) {
  String strError = L"Not enough quota, posted " + IntToStr(iMessages) + L" messages";
  // Do something with strError
}
Run Code Online (Sandbox Code Playgroud)

当在一个简短的COM调用方法结束时运行可以发布数千(例如,9996)消息; 在导致脚本失败的冗长方法调用结束时,它可以发布0.我的结论是消息队列已满是真正导致问题的原因.我的系统的消息队列限制是默认值10000(请参阅"备注"部分.)

调用Application->ProcessMessages()(调用应用程序的消息循环,直到它为空,对于那些不是Delphi/C++ Builder用户的人来说 - …

delphi com winapi c++builder message-queue

6
推荐指数
1
解决办法
2095
查看次数

如何在DLL中创建全局异常处理程序?

我正在使用DLL,有时会引发未处理的异常.我使用madExcept来检测和调试有缺陷的代码,但是当我最终部署我的DLL时,我希望在DLL中包含我自己的全局异常处理程序来记录异常.

所以问题是如何在我的Delphi DLL中设置全局异常处理程序?

delphi delphi-xe

5
推荐指数
2
解决办法
1912
查看次数

MSBuild在Cpp.Targets中使用新的XE4项目搜索"True.dpr"失败

msbuild在RAD Studio XE4中遇到了一些奇怪的错误,我正在寻求帮助来诊断正在发生的事情.我已经遇到了这个问题已经有几个星期了,但是我自己也没有成功解决这个问题 - 时间问得更广泛了.症状是:

  • 通过在IDE中构建和运行的项目,msbuild Project.cbproj似乎可以正常工作
  • 正常运行msbuild Project.cbproj /t:Clean,并删除中间文件.输出的可视扫描不显示任何异常文件被删除 - 只有.obj文件,链接器状态文件,最终EXE等.
  • 但是在清洁或干净结账后运行msbuild Project.cbproj /t:Build或只是简单失败,并显示以下错误消息:msbuild Project.cbproj

Microsoft(R)Build Engine版本3.5.30729.5420 [Microsoft .NET Framework,版本2.0.50727.5472]版权所有(C)Microsoft Corporation 2007.保留所有权利.

Build build 12/09/2013 10:35:03.节点0上的项目"C:\ projects\Project.cbproj"(默认目标).

_PasDepCheck:已修改:Source\Common\resample.pas _PasCoreCompile:Embarcadero Delphi for Win32编译器版本25.0版权所有(c)1983,2013 Embarcadero Technologies,Inc.C:\ Program Files(x86)\ Embarcadero\RAD Studio\11.0\Bin\CodeGear.Cpp.Targets(191 1,5):错误F1026:找不到文件:'True.dpr'完成构建项目"C:\ projects\Project.cbproj"(默认目标) - 失败.

建立失败.

"C:\ projects\Project.cbproj"(默认目标)(1) - >(_PasCoreCompile目标) - > C:\ Program Files(x86)\ Embarcadero\RAD Studio\11.0\Bin\CodeGear.Cpp.Targets(1 911,5):错误F1026:找不到文件:'True.dpr'

0 Warning(s)
1 Error(s)
Run Code Online (Sandbox Code Playgroud)

有些事情让我觉得这个:

  • 它在顶部列出了两个版本的.Net,在方括号中列出了较旧的版本.它可以加载或使用两个框架的一部分吗?
  • True.dpr不存在,也无法找到手动搜索.cbproj文件True.dprTrue …

msbuild c++builder delphi-xe4 c++builder-xe4

5
推荐指数
2
解决办法
1531
查看次数

如何在FireMonkey中将图像绘制为旋转的矩形?

在FireMonkey中,将位图绘制到源矩形很简单:

Canvas.DrawBitmap(FBitmap, ImageSrcRect, ImageDstRect, 1);
Run Code Online (Sandbox Code Playgroud)

而我正在TPaintBox画布上做这件事.我想改为绘制旋转的位图(并缩放,因为目标大小可能与源大小不同.)

特别:

  • 我有两点
  • 图像应放在这两点之间的中心点下方
  • 图像应旋转以跟随两点之间的角度

如下图所示:

期望的轮换

左边一个是我目前可以做的; 在右边是我想做的.

最好的方法是什么?

我试过的

为了保持现有代码简单(例如,绘制到目标矩形,从而缩放结果),我一直在尝试在调用现有的DrawBitmap代码之前向画布的矩阵添加旋转矩阵.例如,

OldMatrix := Canvas.Matrix; // Original, to restore

W := PointB.X - PointA.X;
H := PointA.Y - PointB.Y;
RotationMatrix := TMatrix.CreateRotation(-ArcTan2(H, W));
Canvas.SetMatrix(OldMatrix * RotationMatrix);

Canvas.DrawBitmap(FImage, ImageSrcRect, ImageDstRect, 1);

Canvas.SetMatrix(OldMatrix);
Run Code Online (Sandbox Code Playgroud)

并且有几个变化与现有矩阵相乘,创建了一个全新的矩阵,包括平移和旋转等等.所有这些部分都有效:旋转角度是正确的,但我在使位置保持一致方面遇到了很多麻烦 - 例如,围绕中心点旋转(这甚至不是围绕点旋转位图的顶部,而不是围绕中心旋转.)我发现旋转的图像在底部偏移很好右边象限,但在其他三个中偏移/平移不正确,例如偏得太远,或者剪裁到两点的最左边或最顶端的X或Y位置.我不知道为什么会这样,而且就此而言,我正在寻求帮助.

细节

  • 德尔福10西雅图
  • FireMonkey(在Windows上)
  • 目标是一个TPaintBox任意放置的画布.油漆盒本身可以在上面TScaledLayout.
  • 目标是将绘图位图绘制到绘制框上的旋转目标矩形.

delphi rotation matrix image-rotation firemonkey

5
推荐指数
1
解决办法
1930
查看次数

如何确保Delphi例程的16byte代码对齐?

背景:

我有一个优化的Delphi/BASM例程单元,主要用于繁重的计算.其中一些例程包含内部循环,如果循环开始与DQWORD(16字节)边界对齐,我可以实现显着的加速.如果我知道例程入口点的对齐,我可以确保所讨论的循环按照需要对齐.

据我所知,Delphi编译器将过程/函数与DWORD边界对齐,例如向单元添加函数可能会改变后续函数的对齐.但是,只要我将例程的结尾填充到16的倍数,我就可以确保后续例程同样对齐 - 或未对齐,这取决于第一个例程的对齐方式.因此,我尝试将关键例程放在单元实现部分的开头,并在它们之前放置一些填充代码,以便第一个过程与DQWORD对齐.

这看起来如下所示:

interface

procedure FirstProcInUnit;

implementation

procedure __PadFirstProcTo16;
asm
    // variable number of NOP instructions here to get the desired code length
end;

procedure FirstProcInUnit;
asm //should start at DQWORD boundary
    //do something
    //padding to align the following label to DQWORD boundary
    @Some16BAlignedLabel:
        //code, looping back to @Some16BAlignedLabel
    //do something else
    ret #params
    //padding to get code length to multiple of 16
end;

initialization

__PadFirstProcTo16; //call this here so that it isn't optimised out
ASSERT ((NativeUInt(Pointer(@FirstProcInUnit)) …
Run Code Online (Sandbox Code Playgroud)

delphi memory-alignment

4
推荐指数
2
解决办法
1508
查看次数

如何检测图形卡支持的v3以上的DirectX着色器模型?

我正在编写一个报告系统功能的小工具.一个是安装的图形卡支持的最高着色器模型,我目前正在使用Direct3D 9.0c的设备功能并检查结构VertexShaderVersionPixelShaderVersion字段来检测它D3DCAPS9.

HRESULT hrDCaps = poD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &oCaps);
   if (!FAILED(hrDCaps)) {
      // Pixel and vertex shader model versions. Use the minimum number of each for "the" shader model version
      const int iVertexShaderModel = D3DSHADER_VERSION_MAJOR(oCaps.VertexShaderVersion);
      const int iPixelShaderModel = D3DSHADER_VERSION_MAJOR(oCaps.PixelShaderVersion);
Run Code Online (Sandbox Code Playgroud)

但是,即使对于支持更高模型的卡,这两个值都会返回着色器模型3.以下是GPU-Z为同一张卡返回的内容,例如:

GPU-Z显示着色器模型4.1

这个问题表明,即使在支持更高型号的卡上,DX9也绝不会报告超过SM3,但实际上并没有提到如何解决它.

如何准确获取已安装卡支持的着色器模型? 也就是说,卡的功能,而不是安装的DirectX驱动程序功能.

该实用程序必须在Windows 2000及更高版本上运行,并且可以在未安装图形卡甚至DirectX的系统上运行.我目前正在动态加载DX9,所以在这些系统上,检查优雅地失败了(这没关系.)但我正在寻找类似的解决方案:仍然可以在所有系统上运行,并且在大多数系统上正常工作(检测SM版本).


编辑 - 目的:我没有使用此代码动态更改程序的功能,即选择着色器.我使用它来报告硬件功能作为服务器的"ping",这用于我们很好地了解客户使用的典型硬件,这可以为未来的产品决策提供信息.(例如:有多少客户拥有SM4或更高版本?有多少客户使用64位操作系统?等等)这就是为什么(a)优雅地失败,所以我们知道它失败了,或者(b)获得准确的着色器模型数字是两种首选模式.

编辑 - 答案到目前为止: SigTerm下面的答案建议按顺序实例化DirectX 11,10.1,10和9.0c,并将报告的着色器模型基于哪个版本实例化而没有失败(着色器模型5,4.1,4和DXCAPS in那个顺序.)如果可能的话,我会很感激DX11的代码示例和10种方法.

这可能不是一个可靠的解决方案.例如,我在OSX上的VMWare Fusion虚拟机上运行Windows.Fusion驱动程序在DxDiag中报告DX11,但我从Fusion技术规范中了解到它只支持DX9.0c和着色器模型3.尽管如此,除了这个例外,这种方法似乎是迄今为止最好的方法.

directx shader-model

4
推荐指数
1
解决办法
3942
查看次数

有没有办法在非客户区域中更改Windows Aero颜色?

我注意到Windows已经使Windows的非客户端区域自动成为主题的颜色--Windows Aero.我认为这是一个好主意,因为它使主题在程序和一个通常更好的界面上保持一致.作为一个狡猾的个人,我渴望在这里颠覆微软的意图,并获得一个使用我的程序设置颜色的GUI,而不是操作系统的设置.

思考?

windows user-interface winapi aero

3
推荐指数
1
解决办法
623
查看次数

如何在发布版本中编译依赖于仅调试代码的assert()?

等待!——这个问题并不像听起来那么愚蠢。标题很简单。

我有一些调试代码来验证数据结构的正确性,还有一些断言检查此正确性,我只想在调试版本中启用它们:

{$ifdef DEBUG}
  function Sorted : Boolean;
  function LinearSearchByValue(const T : TType) : NativeInt;
{$endif}
Run Code Online (Sandbox Code Playgroud)

然后在一个方法中:

assert(Sorted);
Run Code Online (Sandbox Code Playgroud)

例如。

在我启用断言的调试版本中,一切都很好。然而,在我禁用断言的发布版本中,该行assert(Sorted);会导致编译器错误E2003 Undeclared identifier: 'Sorted'。完全正确,标识符没有声明,但是断言也被关闭,不应该被评估或生成任何代码。(尝试通过声明方法来欺骗断言,但没有实现会导致正常错误“不满意的前向或外部声明”。它显然也在寻找方法主体。)

这会导致一些混乱的代码,其中根本不应该存在于发布版本中的方法必须被声明并具有主体,以便编译断言,而断言被关闭。

在 Delphi 2010 中,如何声明仅存在于调试版本中的方法,并在断言中使用那些也应仅存在于调试版本中的方法?

更多信息:

  • 我尝试用 包装方法声明{$ifopt C+},它检查断言是否打开。调用assert仍然失败,并出现“未声明的标识符”。

  • 编译器选项肯定是断言被关闭。(我检查了 :))

  • 我尝试将assert使用这些方法的调用包装为{$ifdef DEBUG}. 然而,这很混乱并且不应该是必需的。有一次,它让我担心即使在发布版本中也会编译断言,并且出于性能原因我根本不需要它们。(这没有发生 - 未生成断言代码。)

  • 我当前的策略是始终声明这些方法,但在发布版本中构建 ifdef 方法主体并用虚拟结果填充它。这里的目标是编译所有断言,但方法的开销尽可能小,并且它们的返回值(如果它们实际上在发布版本中被调用)显然是错误的。

  • Delphi 中是否有与 C/C++ 风格的宏等效的东西,ASSERT(x)在发布版本中,宏将被简单地定义为空,导致编译器既看不到也不关心断言内的语句?这是在 C++ 中使用宏的少数干净方法(IMO)之一。

因此,虽然未生成断言,但它们已被编译。这又回到了我的问题:如何最好地混合仅调试方法和断言以及发布版本?

delphi assert delphi-2010

3
推荐指数
1
解决办法
2717
查看次数

如何更改使用DrawThemeTextEx绘制的文本的发光颜色?

DrawThemeTextEx 是用于绘制Windows Vista和7的Aero文本的API,即带有发光光环的文本.

要更改与绘图时所使用的文本颜色DrawThemeTextEx,可以设置crText基于场DTTOPTS结构,并指定DTT_TEXTCOLORdwFlags现场,以指示crText字段包含一个有效的值.但文字背后模糊的发光效果总是呈现白色.设置阴影或边框颜色以及相应的标记对发光颜色没有影响.DTTOPTS结构中的发光颜色没有明显的设置.

发光文字采用自定义文字颜色,但白色发光颜色

在这里,您可以看到自定义文本颜色(红色),但它仍然在文本后面呈现白色模糊的光晕.我想说,黑色发光,因为对于浅色文字颜色,它会使文字更容易阅读.

你如何改变这种白色光晕/发光的颜色?例如,是否存在Dwm*具有效果的API或未记录的标志?

winapi aero aero-glass

3
推荐指数
1
解决办法
742
查看次数

什么阻止将64位Windows平台添加到VCL组件包?

对于大多数Delphi和C++ Builder项目(包括组件包),您可以通过右键单击项目管理器中的"目标平台"项并选择"添加平台",然后在结果中选择"64位Windows"来添加64位Windows目标.对话.

最近在RAD Studio XE4的新安装中安装组件时,我无法对某些组件执行此操作.例如:

仅显示OSX和32位Windows的

这个具体的例子是TMS的高级多边形列表,但它也发生在其他组件包中 - 但不是全部.有些目标可用,对于那些我可以构建包并创建一个使用该组件的64位VCL表单应用程序.

什么阻止Win64目标出现在对话框中,我该如何重新启用它?

delphi target-platform delphi-xe4

3
推荐指数
1
解决办法
2665
查看次数