小编Mar*_*der的帖子

使用打开的句柄删除或重命名文件

Windows API函数CreateFile函数允许您特定所需的访问权限.读,写和删除有三个选项.如果从CreateFile获取请求删除访问的句柄,那么如何使用返回的句柄删除文件?DeleteFile函数采用文件名,而不是句柄.

大图:从我的应用程序保存文件时,我首先写出一个临时文件,然后删除"真实"文件并将临时文件重命名为真实姓名.我已经开始看到搜索索引器或反病毒/间谍软件打开文件进行读取但不允许删除的问题.这会导致我的保存在移动文件时失败.我已经更改了我的开放代码以请求删除访问权限,以确保我可以在保存时删除该文件.

这一切都运行正常,但我还有一个差距,第三方应用程序可以抓取我的文件.由于我对临时文件和真实文件都有一个打开句柄,我一直在寻找一种使用这些句柄执行删除和重命名功能的方法.我能找到的唯一选择是关闭句柄,然后调用DeleteFile和MoveFile函数.实际上我目前正在使用ReplaceFile API函数来执行这些步骤,但它也传入了文件名,除非我先关闭我的句柄,否则它将无法工作.

我仍然需要支持XP,无法开始使用新的事务文件功能.有没有办法保持文件锁定,仍然删除/重命名?

winapi

14
推荐指数
1
解决办法
3545
查看次数

如何将表单作为图像复制到剪贴板

我需要将一个表单(Delphi 2007)作为图像复制到剪贴板,以将用户可以看到的内容粘贴到word文档中.剪贴板部分确实不是问题.问题是如何获取表单的位图.

搜索已经出现了多种选择.

所有这些选项似乎都有不同的问题.我发现的大部分信息似乎都已过时.我似乎没有任何好的资源来比较不同的选项和足够的细节供我做出选择.关于选择哪种选择的任何建议.

我已经在我的表格上尝试了这些并且它们似乎都运行正常,我只是想避免出现问题.有关解决方案的建议吗?

更新:GetFormImage有哪些潜在问题?
Andreas问GetFormImage的问题是什么.希望什么都没有,这是我想要得到答案的一部分.让我担心的是,我的许多搜索结果似乎都在暗示使用GetFormImage的创造性替代方案.我希望答案可以清除水域.

我会很高兴得到很多投票的回答说 - GetFormImage曾经有过一些问题,但现在没有理由不使用它.:-)

至于GetFormImage的实际问题.对于某些用户来说,一个问题是只有表单的可见部分才会出现在图像中(即,您无法捕获隐藏或重叠的窗口).这对我来说不是一个问题,因为我的整个表格都是可见的.

1)更大的问题涉及表单控件所需的特定支持.在德尔福4修正和已知问题页面列表中有该条目(注意它被列为"递延到下").我找不到显示已解决的QC条目:

区域:vcl\core vcl类

参考编号:1088(已发布:12/16/98)
状态:延迟到下一个
Rel日期报告:8/6/98严重性:常见类型:基本
功能故障问题:

问题是GetFormImage大多数嵌套窗口控件如组合框等都被绘制为空白.

2)我也在使用DevExpress控件.他们的控件(在2006年底修复)曾一度不支持 GetFormImage正在使用的PaintTo消息.这在我正在使用的DevExpress版本中修复,但它引发了我的其他问题,我使用的其他控件可能无法正常工作的可能性是多少?

3)这是Embarcadero集团最近的一篇(2010年)帖子.用户在使用GetFormImage时遇到问题,他们在屏幕上显示的部分图表没有出现在最终图像中.他们还需要包含表单标题(我没有),他们采用了本文中概述的Canvas.CopyRect方法.

4)这是TExcellentImagePrinter页面的引用.如果需要,我可以毫无问题地购买他们的产品.该组件看起来像它最近在2002年更新(虽然有一个Delphi 2007试用版).我不知道我是否真的需要走这个方向.

您可以尝试使用GetFormImage或Form.Print.尝试在表单上放下ComboBox,然后调用GetFormImage或Form.Print.如果你打印出来,你会看到ComboBox中的文字吗?没有?别人也没有!这只是打印VCL表单时遇到的问题的一个小例子.

您也可以尝试使用Borland的TI-3155"打印表格的更好方法".当我在Borland工作时,我写了TI作为一个停止间隙测量.虽然它会打印组合框文本,但它会在许多打印机上失败,如果用户调整了表单大小,则无法打印整个表单,并且无法打印隐藏在视图中或部分位于屏幕外的表单.代码基本上生成了一个截图,为了可靠地打印图像,您可能需要查看我们的TExcellentImagePrinter产品!为什么?简而言之,它可能需要几千行低级图形代码才能获得在Windows下打印好的位图.

delphi delphi-2007

10
推荐指数
1
解决办法
9222
查看次数

为什么要检查对象方法中的Assigned(self)?

我正在查看一些代码(Delphi 7),以下检查位于特定对象的每个方法调用的顶部:

if not Assigned(self) then
  raise Exception.CreateRes(@sAbstractError);

  { Real code for this method}
Run Code Online (Sandbox Code Playgroud)

我想这会阻止我尝试在空对象指针上调用方法.但是,一旦我尝试访问该情况下的成员数据,我会得到一个例外,对吗?

这是我以前从未见过的某种标准吗?有问题的对象来自TPersistent.

delphi delphi-7

8
推荐指数
2
解决办法
1368
查看次数

如何在不更改有效文本宽度的情况下绘制缩放文本?

我有一些代码可以自定义绘图.基本上它是具有WYSIWYG编辑器的表单填充程序.编辑器允许设置缩放级别.我的标签宽度相对于表单上的其他内容跳到不同的大小时出现问题.

我用来输出文本的代码示例如下.我很确定这个问题与字体大小的变化有关,与其他所有内容的缩放程度不相符.缩放级别必须更改足以在文本更改之前将字体提升到下一个大小,即使表单上的其他内容在每次更改时都移动了几个像素.

这会导致两个不同的问题 - 文本可能看起来很小,有很多空白区域,或者文本将是两个大的并与下一个控件重叠.当我有一整行文字时,事情看起来很糟糕.单字标签的变化不足以引起任何问题.

我考虑过限制缩放级别 - 现在我有一个1%增量的滑块.但我看不出任何一组水平比其他水平更好.我的表单有多个不同字体大小的标签,可以在不同的时间在较短和较长的时间内跳转.

MultDiv函数对结果进行舍入.我可以截断这个值以确保我总是更小而不是更长,但这看起来同样糟糕,因为这些缩放级别的间隙看起来要大得多.

代码说明:

这是目前在Delphi 7上的.这是我们最后一个没有前进的项目,因此欢迎与更新版本的Delphi相关的答案.

我们调查这个,我确实看到ExtDrawText函数存在.但是,更改为该功能似乎没有任何区别.

边界框的右侧设置为0,并且绘制文本时没有剪切,因为我们用于构建表单定义的工具不跟踪文本的右边界.我们只是将它直观地排列到正确的位置.


procedure OutputText(Canvas: TCanvas; LineNumber: integer; CurrentZoomLevel: integer; FontSize: integer; Text: string);
const
  FormatFlags = DT_BOTTOM + DT_SINGLELINE + DT_NOPREFIX + DT_LEFT + DT_NOCLIP;
var
  OutputBox: TRect;
  ZoomedLineHeight: integer;
begin
  ZoomedLineHeight := MulDiv(UnZoomedLineHeight, CurrentZoomLevel, 96);
  Canvas.Font.Height := -MulDiv(FontSize, CurrentZoomLevel, 96);

  OutputBox.Left := ZoomedLineHeight;
  OutputBox.Right := 0;
  OutputBox.Top := (LineNumber * ZoomedLineHeight);
  OutputBox.Bottom := OutputBox.Top + ZoomedLineHeight;

  DrawText(Canvas.Handle, PChar(Text), length(Text), OutputBox, FormatFlags);
end;
Run Code Online (Sandbox Code Playgroud)

编辑:

在这里使用mghie的答案是我修改过的测试应用程序.缩放代码随着MapMode的设置而消失.但是,TextOut函数似乎仍然选择完整的字体大小.除了我自己不需要计算字体的高度之外,文本似乎没有任何改变 - 地图模式对我来说也是如此.

我确实找到了这个非常有用的网页 …

delphi winapi

8
推荐指数
1
解决办法
4288
查看次数

将属性添加到由TSQL FOR XML Path创建的ElementNode

我试图匹配SQL Server 2008 TSQL查询中的一些XML输出.我匹配的XML可以返回项目列表.列表由属性名称标识 - 而不是节点名称.

XML Path函数将返回一个包装器节点,但我找不到向该节点添加任何属性的方法.在我的情况下,它们将是基于我们正在运行的表名称的硬编码值.

我将'x'作为'x'来保持两个列表分开.在我的实际数据中,这不是问题,因为它们位于不同的节点中.问题是如何将属性添加到"列表"节点.

这是以下示例SQL Fiddle页面:

示例模式

create table Table1 (Value varchar(50)); 
create table Table2 (Value varchar(50)); 

insert Table1 values
('A'), ('B'), ('C');

insert Table2 values
('X'), ('Y'), ('Z');
Run Code Online (Sandbox Code Playgroud)

样品选择

select 
(
 select Value as '@I'
 from Table1
 for XML PATH('L'), TYPE
) as List,
'x' as 'x', -- needed to keep the Lists apart.
(
 select Value as '@I'
 from Table2
 for XML PATH('L'), TYPE
) as List

for XML …
Run Code Online (Sandbox Code Playgroud)

xml t-sql sql-server-2008

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

调用TMouse.GetCursorPos有时会因"调用OS函数失败"而失败

有时我的应用程序会收到以下错误.

通常,当用户离开办公桌离开我的程序时会发生这种情况.当他们回来时,出现了这个错误.

除了对GetCursorPosition进行Windows API调用之外,TMouse.GetCursorPostion不执行任何操作.然后它检查返回值并在失败时调用GetLastError.

"对OS功能的调用失败"对于追踪其原因并不是很有帮助.屏幕保护程序或睡眠模式是否会导致此错误?我可以修改组件以捕获并忽略错误,但如果可能的话,我宁愿知道它首先发生了什么/为什么.

我的应用程序使用的是Delphi 2007,并且Quasidata正在调用Transfer @ Once(v 1.7)组件.

这是调用堆栈:

operating system  : Windows XP Service Pack 3 build 2600
exception number  : 1
exception class   : EOSError
exception message : A call to an OS function failed.

main thread ($d34):
0045e208 UaarSales.exe SysUtils       RaiseLastOSError
0045e191 UaarSales.exe SysUtils       RaiseLastOSError
0045e237 UaarSales.exe SysUtils       Win32Check
004c6de9 UaarSales.exe Controls       TMouse.GetCursorPos
00736d8b UaarSales.exe taoCntrr  3999 TtaoHoverTimer.Timer
004a1d27 UaarSales.exe ExtCtrls       TTimer.WndProc
0047a7a0 UaarSales.exe Classes        StdWndProc
7e4196c2 USER32.dll                   DispatchMessageA
004da230 UaarSales.exe Forms          TApplication.ProcessMessage
004da26a UaarSales.exe …

delphi mouse winapi

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

隐藏Delphi的"应用程序"窗口是否可以?

我们刚刚将我们的应用程序从MDI容器移动到单个文档界面.我们的用户习惯使用MDI父级中的"Windows"菜单并排显示窗口.我们希望训练他们右键单击Windows任务栏并使用那里的窗口管理功能.

使用Delphi应用程序,我们注意到windows shell为隐藏的"Application"窗口留出了空间.因此,如果我只打开两个窗户,它将安排三个房间.应用程序窗口并未真正显示,但仍有空间.

由于我们有两个不同的应用程序,因此情况更糟.如果他们在每个应用程序中只打开一个窗口并想要并排显示它们,那么实际上会尝试占用4个窗口.

因此,我没有看到两个窗口占据屏幕的1/2,而是看到两个窗口占据了桌面的1/4,而屏幕的其余部分则打开了.

我发现在我的应用程序启动时添加一行来隐藏应用程序窗口将解决这个问题.

ShowWindow(Application.Handle,SW_HIDE);

编辑,以防有人没有读到答案.基于Craig的回答,我将windows样式设置为WS_EX_TOOLWINDOW,而不是隐藏窗口. SetWindowLong(Application.Handle,GWL_EXSTYLE,GetWindowLong(Application.Handle,GWL_EXSTYLE)或WS_EX_TOOLWINDOW);

我的(原始)问题是:这是安全的(隐藏应用程序窗口)吗?我想知道我是否可能通过隐藏应用程序窗口来破坏其他内容.我需要注意哪些副作用?有没有更好的方法来解决这个问题?

我正在使用Delphi 2007.这些问题在Windows XP,Vista和7中似乎是一致的.

更新:一些答案似乎认为问题是应用程序表单图标可见.事实并非如此.我已将MainFormOnTaskbar设置为true.

此外,如果您正在测试,请注意Delphi IDE(仅在2007年测试)会让事情变得更糟.试试这个.打开Delphi IDE和两个记事本实例.最小化IDE,但两个记事本都未最小化.右键单击选择"并排显示Windows".您将看到每个记事本占据屏幕的1/3.关闭IDE并再次选择"并排显示Windows",每个屏幕占据屏幕的一半.

delphi

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

如何防止两个对齐底部控件与反转顺序?

我有一个包含三个主要组件的表单:

  1. 设置为与客户端对齐的FlowPanel
  2. 第二个FlowPanel设置为Align to Bottom
  3. StatusBar设置为Align to Bottom.

一切都开始看起来很棒.但是与底部对齐的FlowPanel也设置为AutoSize.它包含一个可以自行折叠的面板.内部面板包含用户可以决定隐藏的摘要信息.这会将FlowPanel的大小降低到非常小的尺寸但不会完全消失.仍然有一个按钮,用户可以在其中重新展开摘要面板.

面板重新展开导致FlowPanel增长时出现问题.那时状态栏和FlowPanel的顺序相反.它们仍然设置为对齐底部,但现在状态栏位于我的FlowPanel之上.

我可以在没有折叠面板的测试应用程序中复制它,只需在表单上放置按钮即可查看底部流量面板的高度.如果高度增加,则订单会发生变化.如果它减少了,那么一切都保持相同的顺序.我的测试表单中唯一的代码是:

FlowPanel2.Height := FlowPanel2.Height * 2;
Run Code Online (Sandbox Code Playgroud)

我也测试了这个,底部面板是常规TPanel而不是FlowPanel,结果相同.

关于为什么会发生这种情况以及如何预防的任何想法?

移动状态栏图像

delphi vcl delphi-2007

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

FireDAC - 在宏扩展后显示SQL

我试图在FireDAC中使用宏来预处理我的SQL查询.我在数据模块上有一个TADQuery对象,其SQL设置如下:

Select * from MyTable
  join OtherTable on MyTable.Key = OtherTable.Key
&Where
Run Code Online (Sandbox Code Playgroud)

然后在我的代码中我这样做:

WhereClause = 'stuff based on my form';
Query.MacroByName('Where').AsRaw := WhereClause;
Query.Open;
Run Code Online (Sandbox Code Playgroud)

这对于复杂的查询非常有用,因为它允许我使用SQL属性编辑器确保我的字段和连接条件是正确的.

我的问题是由于我的where子句导致SQL语句失效. 有没有办法在预处理之后看到要执行的SQL?现在我正在捕获FireDac错误并显示EADDBEngineException对象上的SQL.但是仍然显示我的原始SQL与宏.如果我在错误发生后无法访问它,那么无论如何都要强制进行宏替换,这样我就可以查看调试器中的SQL来帮助我查看错误.

如果重要,我将连接到MS Access数据库,目标是在不久的将来转移到SQL Server.

delphi delphi-xe3 firedac

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

如何将非绑定列添加到 DevExpress DB QuantumGrid

我正在使用这些组件:

UniDac for connection to mysql database
DevExpress for QuantumGrid
Run Code Online (Sandbox Code Playgroud)

IDE:

Embarcadero Rad Studio XE2
Run Code Online (Sandbox Code Playgroud)

我有一个具有一个级别的 cxGrid 组件和一个指定为该级别视图的 cxGrid1DBTableView。我可以从我的数据库中获取数据并在网格中对其进行编辑。我想添加一个不在绑定数据集中的列。当我将列属性值指定为CheckBox 时,我可以看到该列,但无法通过单击将值从未选中更改为选中。该字段没有分配给它的DataBinding。我尝试了其他类型的属性,但都是一样的,我无法更改网格中的行值。

这几天我一直在寻找解决这个问题的方法,所以我希望你们能帮助我。

delphi vcl devexpress delphi-xe2 unidac

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

创建 DataModule 后如何更改其所有者?

我正在尝试将 DataModule 传递给表单构造函数中的表单。我还希望表单成为 DataModule 的“所有者”,以便表单在关闭时会销毁 DataModule。这就产生了两个对象在其构造函数中需要彼此的问题。

我尝试在创建后设置 DataModule 的所有者,但这是一个只读属性。

我的第二种形式如下所示:

type
  TSecondPopup = class(TForm)
  private
    FMyData: TMyData;
  public
    constructor Create(MyData: TMyData); reintroduce;
  end;

var
  SecondPopup: TSecondPopup;

implementation

{$R *.dfm}


constructor TSecondPopup.Create(MyData: TMyData);
begin
  FMyData := MyData;

  inherited Create(nil);
end;
Run Code Online (Sandbox Code Playgroud)

我的数据模块中没有特殊的代码。

在我的主窗体中,我想在显示第二个窗体时执行类似的操作:

procedure TMainApp.Button1Click(Sender: TObject);
var
  MyData: TMyData;
  SecondPopup: TSecondPopup;
begin
  MyData := TMyData.Create(nil);
  SecondPopup := TSecondPopup.Create(MyData);

  // Can't change owner now.  It is a read only property. 
  // MyData.Owner := SecondPopup;

  SecondPopup.Show;
end;
Run Code Online (Sandbox Code Playgroud)

我知道我可以将 DataModule 更改为表单上的属性。然后我可以先创建表单,然后创建设置所有者的数据模块,最后在表单上设置属性。我正在尝试在这个项目上使用构造函数依赖注入。当我有一个主表单传递给多个表单的共享数据模块时,它工作得很好。在这种情况下,主窗体将保留数据模块直至其存在。在这种情况下,只有一种表单需要此数据模块,因此我想通过设置所有者来强制它管理数据模块的生命周期。

另一种选择是在关闭第二个表单时显式释放 DataModule。然而,该表单无法知道调用者是否也将数据模块传递给了不同的表单。

有没有办法使用构造函数来注入我的对象,但仍然获得表单来管理生命周期?

目前使用Delphi …

delphi

2
推荐指数
1
解决办法
2832
查看次数

WriteComponentResFile不包括动态添加到TTabSheet的组件

我试图将一组使用自定义工具创建的表单转换为Delphi表单.我试图在运行时添加所有必要的组件,然后使用WriteComponentResFile来创建DFM文件.

在我尝试添加TPageControl和TabSheets之前,我的所有初始测试看起来都很好.当前表单可以有多个页面,所以我将使用PageControl镜像它.问题是我添加到TabSheet的任何组件都没有流式传输到DFM.如果我显示表单看起来很好,但WriteComponentResFile缺少某些东西.

我正在写一个相应的pas文件,所以我可以在完成后在IDE中打开它.目标是远离自定义表单设计器,并开始使用Delphi IDE作为表单设计器.

下面是一些示例代码,展示了我如何创建组件:

procedure WriteFormAsDFM(OutputFileName: string);
var
  PageIndex: integer;
  PageCount: Integer;
  OutputForm: TForm;
  Pages: TPageControl;
  NewPage: TTabSheet;
  NewLabel: TLabel;
begin

  OutputForm := TForm.Create(nil);
  OutputForm.Name := ChangeFileExt(ExtractFileName(OutputFileName), '');
  OutputForm.Caption := OutputForm.Name;
  OutputForm.Height := 300;
  OutputForm.Width := 300;

  Pages := TPageControl.Create(OutputForm);
  Pages.Parent := OutputForm;
  Pages.Top := 50;
  Pages.Left := 0;
  Pages.Height := 200;
  Pages.Width := 200;

  NewLabel := TLabel.Create(OutputForm);
  NewLabel.Parent := OutputForm;
  NewLabel.Caption := 'Label on Form';

  //write pages
  PageCount := 2;

  for PageIndex := 0 to PageCount - 1 …
Run Code Online (Sandbox Code Playgroud)

delphi delphi-2007

0
推荐指数
1
解决办法
503
查看次数