This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / tooltip.cs
1 //
2 // System.Windows.Forms.ToolTip
3 //
4 // Author:
5 //   stubbed out by Jackson Harper (jackson@latitudegeo.com)
6 //      Dennis Hayes (dennish@raytek.com)
7 //   implemented by Aleksey Ryabchuk (ryabchuk@yahoo.com)
8 //
9 // (C) 2002/3 Ximian, Inc
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32 using System.ComponentModel;
33 using System.Runtime.InteropServices;
34 using System.Collections;
35
36 namespace System.Windows.Forms {
37
38         // <summary>
39         // Tooltip control
40         // </summary>
41
42         public sealed class ToolTip : Component, IExtenderProvider {
43                 bool active = true;
44                 int  automaticDelay = 500;
45                 int  autoPopDelay   = 5000;
46                 int  initialDelay   = 500;
47                 int  reshowDelay    = 100;
48                 bool showAlways     = false;
49                 const int MAX_SHORT = 32767;
50
51                 NativeWindow tooltipWnd = new NativeWindow ();
52                 Hashtable tooltipTexts  = new Hashtable();
53
54                 public ToolTip() {
55                         createToolTipWindow ( );
56                 }
57
58                 public ToolTip(IContainer cont) {
59                         createToolTipWindow ( );
60                         cont.Add ( this );
61                 }
62
63                 public bool Active {
64                         get {   return active;  }
65                         set {
66                                 if ( active != value ) {
67                                         active = value;
68                                         activateToolTip ( active );
69                                 }
70                         }       
71                 }
72
73                 public int AutomaticDelay {
74                         get {   return automaticDelay;  }
75                         set {
76                                 if ( automaticDelay != value ) {
77                                         automaticDelay = value;
78                                         AutoPopDelay = 10*automaticDelay;
79                                         InitialDelay = automaticDelay;
80                                         ReshowDelay = automaticDelay / 5;
81                                         setToolTipDelay ( ToolTipControlDelayFlags.TTDT_AUTOMATIC, automaticDelay );
82                                 }
83                         }       
84                 }
85
86                 public int AutoPopDelay{
87                         get {   return autoPopDelay; }
88                         set {
89                                 autoPopDelay = value;
90                                 setToolTipDelay ( ToolTipControlDelayFlags.TTDT_AUTOPOP, autoPopDelay );
91                         }
92                 }
93
94                 public int InitialDelay {
95                         get {   return initialDelay; }
96                         set {
97                                 initialDelay = value;
98                                 setToolTipDelay ( ToolTipControlDelayFlags.TTDT_INITIAL, initialDelay );
99                         }
100                 }
101
102                 public int ReshowDelay {
103                         get {   return reshowDelay; }
104                         set {
105                                 reshowDelay = value;
106                                 setToolTipDelay ( ToolTipControlDelayFlags.TTDT_RESHOW, reshowDelay );
107                         }
108                 }
109
110                 public bool ShowAlways {
111                         get {   return showAlways ; }
112                         set {
113                                 if ( showAlways != value ) {
114                                         bool OldStyle = showAlways;
115                                         showAlways = value;
116                                         if ( tooltipWnd.Handle != IntPtr.Zero )
117                                                 Win32.UpdateWindowStyle ( tooltipWnd.Handle,
118                                                                           OldStyle ? (int)ToolTipControlStyles.TTS_ALWAYSTIP : 0,
119                                                                           value ? (int)ToolTipControlStyles.TTS_ALWAYSTIP : 0 );
120                                 }
121                         }
122                 }
123                 
124                 public void RemoveAll() {
125                         foreach (object o in tooltipTexts.Keys) {
126                                 Control target = o as Control;
127                                 if ( target != null ) {
128                                         removeToolTip ( target );
129                                         target.HandleCreated    -= new System.EventHandler( control_HandleCreated );
130                                         target.HandleDestroyed -= new System.EventHandler ( control_HandleDestroyed );
131                                 }
132                         }
133                         tooltipTexts.Clear ( );
134                 }
135
136                 public void SetToolTip(Control control, string caption) {
137                         if ( caption == null || caption.Length == 0 ) {
138                                 if ( tooltipTexts.Contains ( control )  ) {
139                                         removeToolTip ( control );                                      
140                                         control.HandleCreated   -= new System.EventHandler( control_HandleCreated );
141                                         control.HandleDestroyed -= new System.EventHandler ( control_HandleDestroyed );
142                                         tooltipTexts.Remove ( control );
143                                         return;
144                                 }
145                         }
146                         if ( !tooltipTexts.Contains ( control )  ) {
147                                 control.HandleCreated   += new System.EventHandler( control_HandleCreated );
148                                 control.HandleDestroyed += new System.EventHandler ( control_HandleDestroyed );
149                                 if ( control.IsHandleCreated )
150                                         addTool ( control, caption );
151                         }
152                         else {
153                                 if ( control.IsHandleCreated )
154                                         updateTipText ( control, caption );
155                         }
156                         tooltipTexts[ control ] = caption;
157                 }
158
159                 public string GetToolTip( Control control ) {
160                         string text = (string) tooltipTexts[control];
161                         if ( text == null )
162                                 text = string.Empty;
163                         return text;
164                 }
165
166                 public override string ToString() {
167                         return "[" + GetType().FullName.ToString() + "] InitialDelay: " + InitialDelay.ToString() +
168                                 ", ShowAlways: " + ShowAlways.ToString();
169                 }
170
171                 bool IExtenderProvider.CanExtend( object extendee ){
172                         return ( extendee is Control ) && !( extendee is ToolTip );
173                 }
174                 
175                 private void createToolTipWindow ( ) {
176                         if ( tooltipWnd.Handle == IntPtr.Zero ) {
177                                 initCommonControlsLibrary ( );
178                                 
179                                 CreateParams pars = new CreateParams ( );
180
181                                 pars.ClassName = Win32.TOOLTIPS_CLASS;
182                                 pars.ExStyle = (int) WindowExStyles.WS_EX_TOPMOST;
183                                 pars.Style = (int) ToolTipControlStyles.TTS_NOPREFIX;
184                                 
185                                 if ( ShowAlways )
186                                         pars.Style |= (int)ToolTipControlStyles.TTS_ALWAYSTIP;
187
188                                 tooltipWnd.CreateHandle ( pars );
189
190                                 Win32.SetWindowPos ( tooltipWnd.Handle,
191                                                 SetWindowPosZOrder.HWND_TOPMOST,
192                                                 0, 0, 0, 0, 
193                                                 SetWindowPosFlags.SWP_NOMOVE |
194                                                 SetWindowPosFlags.SWP_NOSIZE |
195                                                 SetWindowPosFlags.SWP_NOACTIVATE );
196
197                                 Win32.SendMessage ( tooltipWnd.Handle,
198                                         (int)ToolTipControlMessages.TTM_SETMAXTIPWIDTH,
199                                         0, MAX_SHORT );
200
201                                 activateToolTip ( Active );
202                         }
203                 }
204
205                 private void initCommonControlsLibrary ( ) {
206                         INITCOMMONCONTROLSEX    initEx = new INITCOMMONCONTROLSEX();
207                         initEx.dwICC = CommonControlInitFlags.ICC_BAR_CLASSES;
208                         Win32.InitCommonControlsEx(initEx);
209                 }
210
211                 private void control_HandleCreated(object sender, System.EventArgs e) {
212                         Control ctrl = sender as Control;
213                         if ( ctrl != null && tooltipTexts.Contains ( ctrl ) )
214                                 addTool ( ctrl, GetToolTip ( ctrl ) );
215                 }
216
217                 private void control_HandleDestroyed(object sender, System.EventArgs e) {
218                         Control ctrl = sender as Control;
219                         if ( ctrl != null && tooltipTexts.Contains ( ctrl ) )
220                                 removeToolTip ( ctrl );
221                 }
222
223                 private void addTool ( Control target, string tiptext ) {
224                         TOOLINFO ti     = new TOOLINFO( );
225                         ti.cbSize       = (uint)Marshal.SizeOf( ti );
226                         ti.hwnd         = target.Handle;
227                         ti.uId          = (uint)target.Handle.ToInt32();
228                         ti.lpszText     = tiptext;
229                         ti.uFlags       = (int)(ToolTipFlags.TTF_SUBCLASS | ToolTipFlags.TTF_IDISHWND);
230                         sendMessageHelper ( ToolTipControlMessages.TTM_ADDTOOL, ref ti);
231                 }
232
233                 private void updateTipText ( Control target, string tiptext ) {
234                         TOOLINFO ti     = new TOOLINFO( );
235                         ti.cbSize       = (uint)Marshal.SizeOf( ti );
236                         ti.hwnd         = target.Handle;
237                         ti.uId          = (uint)target.Handle.ToInt32();
238                         ti.lpszText     = tiptext;
239                         sendMessageHelper ( ToolTipControlMessages.TTM_UPDATETIPTEXT, ref ti );
240                 }
241
242                 private void activateToolTip ( bool avtivate ) {
243                         if ( tooltipWnd.Handle != IntPtr.Zero )
244                                 Win32.SendMessage ( tooltipWnd.Handle,
245                                         (int)ToolTipControlMessages.TTM_ACTIVATE, avtivate ? 1 : 0, 0 );
246                 }
247
248                 private void removeToolTip ( Control target ) {
249                         if ( target.IsHandleCreated ) {
250                                 TOOLINFO ti     = new TOOLINFO( );
251                                 ti.cbSize       = (uint)Marshal.SizeOf( ti );
252                                 ti.hwnd         = target.Handle;
253                                 ti.uId          = (uint)target.Handle.ToInt32();
254                                 sendMessageHelper ( ToolTipControlMessages.TTM_DELTOOL, ref ti );
255                         }
256                 }
257
258                 private void setToolTipDelay ( ToolTipControlDelayFlags flag, int DelayTime ) {
259                         if ( tooltipWnd.Handle != IntPtr.Zero )
260                                 Win32.SendMessage ( tooltipWnd.Handle,
261                                         (int)ToolTipControlMessages.TTM_SETDELAYTIME,
262                                         (int)flag, Win32.MAKELONG( DelayTime, 0) );
263                 }
264
265                 private void sendMessageHelper ( ToolTipControlMessages mes, ref TOOLINFO ti ) {
266                         if ( tooltipWnd.Handle != IntPtr.Zero ) {
267                                 IntPtr ptr      = Marshal.AllocHGlobal ( Marshal.SizeOf ( ti ) );
268                                 Marshal.StructureToPtr( ti, ptr, false );
269                                 Win32.SendMessage ( tooltipWnd.Handle , (int)mes, 0, ptr.ToInt32() );
270                                 Marshal.FreeHGlobal ( ptr );
271                         }
272                 }
273
274                 protected override void Dispose( bool disposing )
275                 {
276                         lock ( this ) {
277                                 try {
278                                         if ( disposing ) {
279                                                 tooltipWnd.DestroyHandle ( );
280                                         }
281                                 }
282                                 finally {
283                                         base.Dispose ( disposing ); 
284                                 }
285                         }
286                 }
287         }
288 }