来源:远方网络 | 2005-12-31 9:38:25 | (有2212人读过)
35 如何实作 BorderStyle 属性?
在控件设定有没有边框之后要重新建立 window handle:
FBorderStyle: TBorderStyle;
procedure SetBorderStyle(Style: TBorderStyle);
property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle;
procedure CreateParams(var Params: TCreateParams); override;
procedure TMyControl.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
if FBorderStyle = bsSingle then
Params.Style := Params.Style or WS_BORDER
else
Params.Style := Params.Style and not WS_BORDER;
end;
procedure TMyControl.SetBorderStyle(Style: TBorderStyle);
begin
if Style <> FBorderStyle then
begin
FBorderStyle := Style;
// 重新建立window handle
RecreateWnd;
end;
end;
36 当组件重绘时如何防止闪动的情况?
如果组件的 ComponentStyle 属性没有包含 csOpaque 旗帜的话,呼叫 Invalidate方法时 会导致组件的背景先被擦掉再重绘。如果你在 Paint 方法中绘制背景,那你应该在组件的建构函式中加上:
ComponentStyle := ComponentStyle + [csOpaque];
引起闪动另一个原因可能是 WM_ERASEBKGND 讯息的处理。当 VCL 控件收到一个 WM_ERASEBKGND 讯息时,它会将组件的背景擦掉然后设定成预设的颜色。如果你的组件衍生自 TWinControl,而且组件的颜色与背景颜色不同(例如图形),每次重画以前都会将组件先清成背景颜色再重绘,这就是造成闪动的原因了!
解决的方法不难,你必须告诉 Windows 你要自行解决『所有的』绘图动作。不过有一个前提是,你一定要确定你的 Paint 方法将整个组件都画过,如果你漏了什么地方忘了画,那个部分的资料会由随机数组成,你能想见这情况吗?使用这个方法可以加速你的组件绘制动作(稍微快一点点),因为少了一个填满背景颜色的动作。
type
TMyComponent = class (TWinControl)
...
protected
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
...
end;
procedure TBMyComponent.WMEraseBkgnd(var Message: TWMEraseBkgnd);
begin
// 不要重绘背景,这会造成组件闪动
Message.Result := 0
end;
37 为什么我的组件得不到方向键的讯息?
你必须拦截 WM_GETDLGCODE 才能处理方向键的讯息,在 WM_GETDLGCODE 的讯息处理 者中传回 DLGC_WANTARROWS。如果你不这样做,那方向键的功用就只能用来移动窗口焦点而己。
想要你的组件能够处理方向键,你必须要拦截 CM_WANTSPECIALKEY 组件讯息。 CM_WANTSPECIALKEY 组件讯息提供你比拦截 WM_GETDLGCODE 窗口讯息更容易且灵活的判断方法来决定是否需要某些特殊键的讯息。当控件收到任何一个特殊键时就会送出CM_WANTSPECIALKEY 组件讯息给控件。
特殊键包括:VK_TAB、VK_LEFT、VK_RIGHT、VK_UP、VK_DOWN、VK_RETURN、VK_EXECUTE 、VK_ESCAPE 及 VK_CANCEL。如果讯息传回值是非零值,这个键就会被送至 KeyPress 方法以供处理,否则这个键的讯息会被送至组件的父控件,以预设方式来处理。
一个简单的范例:
type
TMyComponent = class (TWinControl)
...
protected
procedure CMWantSpecialKey(var Message: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
...
end;
procedure TMyComponent.CMWantSpecialKey(var Message: TCMWantSpecialKey); begin
inherited;
// 我们只想处理向左方向键,其它的特殊键都给 Windows 处理
if Message.CharCode = VK_LEFT then
Message.Result := 1;
end;
CM_WANTSPECIALKEY 组件讯息比 WM_GETDLGCODE 讯息更具有弹性的地方在这儿。我们甚至可以根据是按下的是哪个特殊键才决定是否处理这个键。例如,你的控件有三张影像,你可以让使用者利用左右方向键来回检视它们,如果翻到最后一张影像再按向右键时,焦点就让它离开组件,剩下的全部都让 Delphi 来处理。
38 有没有与 Visual Basic『DoEvents』同样功能的函式?
有。Application.ProcessMessages方法。
|