分享
 
 
 

Another Way to Drag a Window

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

The most common way to move an application window is to drag it by its title bar. The following article lets you provide dragging capabilities for Delphi forms without a caption, so the user can move them by clicking anywhere on their client area.

Step aside, junior

For example, consider the case of a Windows application that doesn't have a title bar, how can we move such a window?. In fact, it's possible to create windows with a nonstandard title bar and even non rectangular forms. In this case, how could Windows know where the borders and the corners of the window are?

Messages

The Windows operating system is heavily based on messages. For example, when you click on a window or a control, Windows sends it a wm_LButtonDown message, with additional information about where the mouse cursor is and which control keys are currently pressed. Sounds familiar? Yes, this is nothing more than an OnMouseDown event in Delphi.

Similarly, Windows sends a wm_NCHitTest message whenever a mouse event occurs, that is, when the cursor moves, or when a mouse button is pressed or released. If the mouse is not captured, the message is sent to the window beneath the cursor. Otherwise, the message is sent to the window that has captured the mouse.

If we can make Windows think that the user is dragging (has clicked on) the title bar rather than the client area, then the user could drag the window by clicking in the client area. The easiest way to do this is to "fool" Windows into thinking that you're actually clicking on the title bar of a form. We will do this by handling the WM_NCHitTest windows message. Here's what you have to do:

1. insert the following line into your form's "Private declarations" section (message handling procedure declaration):

procedure WMNCHitTest(var Msg: TWMNCHitTest);

message wm_NCHitTest;

2. add the following code into the "implementation" section of your form's unit (where Form1 is assumed form name):

procedure TForm1.WMNCHitTest(var Msg: TWMNCHitTest);

begin

inherited;

if Msg.Result = htClient then

Msg.Result := htCaption;

end;

The first line of code in the message handler calls the inherited method to obtain the default handling for the wm_NCHitTest message.

The if part in the procedure intercepts and changes your window's behavior. This is what actually happens: when the operating system sends a wm_NCHitTest message to the window, together with the mouse coordinates, the window returns a code that states which portion of itself has been hit. The important piece of information, for our task, is in the value of the Msg.Result field. At this point, we have an opportunity to modify the message result.

This is what we do: if the user has clicked in the form's client area we make Windows to think the user clicked on the title bar. In Object Pascal "words": if the message return value is HTCLIENT, we simply change it to HTCAPTION.

Be carefull: mouse events, no more!

By changing the default behaviour of our forms we remove the ability of Windows to notify you when the mouse is over the client area. One side effect of this trick is that your form will no longer generate events for mouse messages.

Captionless-Borderless Window

If you want a captionless borderless window similar to a floating toolbar, set the Form's Caption to an empty string, disable all of the BorderIcons, and set the BorderStyle to bsNone.

Show window contents while dragging

To show the window contents while dragging the window we can use the next API procedure calls:

//to Show window contents while dragging:

SystemParametersInfo

(SPI_SETDRAGFULLWINDOWS, 1, nil, 0);

//to disable this option call the function:

SystemParametersInfo

(SPI_SETDRAGFULLWINDOWS, 0, nil, 0);

More wm_NCHitTest tricks

If you look more carefully at the wm_NCHitTest message you'll see that return value of the function indicates the position of the cursor hot spot. This enables us to play some more with the message to create strange results.

. The following code fragment will prevent users to close your forms by clicking on their Close buttons.

if Msg.Result = htClose then

Msg.Result := htNowhere;

. If the user is trying to move the form by clicking on the caption bar and dragging, the code replaces the result of the message with a result which indicates the user clicked on the client area. This prevents the user from moving the window with the mouse (opposite to what we were doing in the begging of the article).

if Msg.Result = htCaption then

Msg.Result := htClient;

. A "funny" peace of code, minimize is maximize and maximize is minimize.

if Msg.Result = htMaxButton then

Msg.Result := htMaxButton

else if Msg.Result = htMinButton then

Msg.Result := htMinButton;

But, I have components on a form!?

In most cases we'll have some components on a form. Let's say, for example, that one Panel object is on a form. If Align property of a panel is set to alClient, the Panel fills the entire client area so that it is impossible to select the parent form by clicking on it. The code above will not work! Why? The code above will not work because the mouse is always moving over the Panel component not the form.

To move our form by dragging a panel on the form we have to add few lines of code in the OnMouseDown event procedure for the Panel component:

procedure TForm1.Panel1MouseDown

(Sender: TObject; Button: TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

ReleaseCapture;

SendMessage(Form1.Handle, WM_SYSCOMMAND, 61458, 0);

end;

Note: this code will not work with non-window controls such as TLabel components.

Moving, moving... That's it. If you have some discussion ideas on this topic, please post to the Delphi Programming Forum.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有