1 /** DGui project file. 2 3 Copyright: Trogu Antonio Davide 2011-2013 4 5 License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). 6 7 Authors: Trogu Antonio Davide 8 */ 9 module dgui.tooltip; 10 11 import dgui.core.controls.subclassedcontrol; 12 13 enum ToolTipIcons 14 { 15 none = TTI_NONE, 16 info = TTI_INFO, 17 warning = TTI_WARNING, 18 error = TTI_ERROR, 19 } 20 21 class ToolTip: SubclassedControl 22 { 23 private ToolTipIcons _ttIcon = ToolTipIcons.none; 24 private bool _creating = false; 25 private Control _ctrl; 26 private string _title; 27 28 public override void dispose() 29 { 30 if(this._ctrl) 31 { 32 this.removeTool(); 33 } 34 35 super.dispose(); 36 } 37 38 private void addTool(Control c) 39 { 40 this._ctrl = c; 41 42 TOOLINFOW ti; 43 44 ti.cbSize = TOOLINFOW.sizeof; 45 ti.uFlags = TTF_SUBCLASS | TTF_IDISHWND; 46 ti.lpszText = cast(wchar*)LPSTR_TEXTCALLBACKW; 47 ti.hwnd = c.parent ? c.parent.handle : c.handle; 48 ti.uId = cast(uint)c.handle; 49 50 this.sendMessage(TTM_ADDTOOLW, 0, cast(LPARAM)&ti); 51 } 52 53 private void removeTool() 54 { 55 TOOLINFOW ti; 56 57 ti.cbSize = TOOLINFOW.sizeof; 58 ti.hwnd = this._ctrl.parent ? this._ctrl.parent.handle : this._ctrl.handle; 59 ti.uId = cast(uint)this._ctrl.handle; 60 61 this.sendMessage(TTM_DELTOOLW, 0, cast(LPARAM)&ti); 62 this._ctrl = null; 63 } 64 65 @property public void icon(ToolTipIcons tti) 66 { 67 this._ttIcon = tti; 68 69 if(this.created) 70 { 71 this.sendMessage(TTM_SETTITLEW, this._ttIcon, cast(LPARAM)toUTFz!(wchar*)(this._title)); 72 } 73 } 74 75 @property public string title() 76 { 77 return this._title; 78 } 79 80 @property public void title(string s) 81 { 82 this._title = s; 83 84 if(this.created) 85 { 86 this.sendMessage(TTM_SETTITLEW, this._ttIcon, cast(LPARAM)toUTFz!(wchar*)(this._title)); 87 } 88 } 89 90 @property public void baloonTip(bool b) 91 { 92 this.setStyle(TTS_BALLOON, b); 93 } 94 95 @property public void closeButton(bool b) 96 { 97 this.setStyle(TTS_CLOSE, b); 98 } 99 100 @property public void alwaysTip(bool b) 101 { 102 this.setStyle(TTS_ALWAYSTIP, b); 103 } 104 105 @property public override void parent(Control c) 106 { 107 if(this._creating) 108 { 109 super.parent = c; 110 } 111 else 112 { 113 throwException!(DGuiException)("A ToolTip cannot have a parent"); 114 } 115 } 116 117 public final void activate(Control c) 118 { 119 if(!this.created) 120 { 121 this._creating = true; 122 this.parent = c.parent ? c.parent : c; 123 this.show(); 124 this._creating = false; 125 } 126 127 if(this._ctrl !is c) 128 { 129 if(this._ctrl) 130 { 131 this.removeTool(); 132 } 133 134 this.addTool(c); 135 } 136 137 this.sendMessage(TTM_ACTIVATE, true, 0); 138 } 139 140 public override void show() 141 { 142 if(this._creating) 143 { 144 super.show(); 145 } 146 else 147 { 148 throwException!(DGuiException)("Cannot create a ToolTip directly"); 149 } 150 } 151 152 protected override void createControlParams(ref CreateControlParams ccp) 153 { 154 ccp.superclassName = WC_TOOLTIP; 155 ccp.className = WC_DTOOLTIP; 156 ccp.defaultBackColor = SystemColors.colorInfo; 157 ccp.defaultForeColor = SystemColors.colorInfoText; 158 159 this.setStyle(WS_POPUP | TTS_NOPREFIX, true); 160 this.setExStyle(WS_EX_TOPMOST | WS_EX_TOOLWINDOW, true); 161 162 /* According To MSDN: 163 The window procedure for the tooltip control automatically sets the size, position, and visibility of the control. 164 The height of the tooltip window is based on the height of the font currently selected into the device context 165 for the tooltip control. 166 The width varies based on the length of the string currently in the tooltip window. */ 167 this.bounds = Rect(CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT); 168 169 ToolTip.setBit(this._cBits, ControlBits.cannotAddChild | ControlBits.useCachedText, true); 170 super.createControlParams(ccp); 171 } 172 173 protected override void onReflectedMessage(ref Message m) 174 { 175 if(m.msg == WM_NOTIFY) 176 { 177 NMHDR* pNotify = cast(NMHDR*)m.lParam; 178 179 if(pNotify.code == TTN_GETDISPINFOW) 180 { 181 NMTTDISPINFOW* pDispInfo = cast(NMTTDISPINFOW*)pNotify; 182 pDispInfo.lpszText = toUTFz!(wchar*)(this.text); 183 } 184 } 185 186 super.onReflectedMessage(m); 187 } 188 189 protected override void onHandleCreated(EventArgs e) 190 { 191 if(this._ttIcon !is ToolTipIcons.none || this._title.length) 192 { 193 this.sendMessage(TTM_SETTITLEW, this._ttIcon, cast(LPARAM)toUTFz!(wchar*)(this._title)); 194 } 195 196 SetWindowPos(this._handle, cast(HWND)HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 197 super.onHandleCreated(e); 198 } 199 }