forked from dictation-toolbox/natlink
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MessageWindow.cpp
305 lines (249 loc) · 7.71 KB
/
MessageWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*
Python Macro Language for Dragon NaturallySpeaking
(c) Copyright 1999 by Joel Gould
Portions (c) Copyright 1999 by Dragon Systems, Inc.
secdthrd.cpp
This file contains the code which handles the second thread used in the
natlink module. The second thread provised a dialog in which we display
Python error messages
April 25, 1999
- packaged for external release
March 3, 1999
- initial version
*/
#include "stdafx.h"
#include "Resource.h"
#include "MessageWindow.h"
#include <richedit.h>
// This is the message we send to the other thread to add text to the output
// window. wParam = TRUE for error text, FALSE for normal text. lParam is
// the pointer to a string to display. The thread should delete the string
// when finished.
#define WM_SHOWTEXT (WM_USER+362)
// Send this message to the other thread to destroy the window and exit the
// thread.
#define WM_EXITTHREAD (WM_USER+363)
// Send this message to the output window to update it as specified.
#define WM_UPDATEWINDOW (WM_USER+364)
// WPARAM flags for the WM_UPDATEWINDOW message.
#define IDR_MENU_ENABLE_IDD_EXIT 0x01
#define IDR_MENU_DISABLE_IDD_RELOAD 0x02
#define IDR_MENU_DISABLE 0x04
// The color for error messages
#define DARKRED RGB( 128, 0, 0 )
//---------------------------------------------------------------------------
// Called when a message is sent to the dialog box. Return FALSE to tell
// the dialog box default window message handler to process the message.
INT_PTR CALLBACK dialogProc(
HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
// This is the threads copy of the MessageWindow class pointer. I
// supposed that this should not really be global but stored in some
// thread or windows storage instead. Oh, well.
static MessageWindow * s_pSecdThrd = NULL;
switch( msg )
{
case WM_CREATE:
return TRUE;
case WM_INITDIALOG:
// save a pointer to the message window for later
s_pSecdThrd = (MessageWindow *)lParam;
// hide the window to start with
ShowWindow( hWnd, SW_HIDE );
return TRUE;
case WM_UPDATEWINDOW:
HINSTANCE hInstance;
HMENU hMenu, hSubMenu;
UINT uFlags, uIDItem;
// destroy the current menu
hMenu = GetMenu( hWnd );
if( hMenu )
{
DestroyMenu( hMenu );
}
// load the pop-up menu
hInstance = _Module.GetModuleInstance();
hMenu = LoadMenu( hInstance, MAKEINTRESOURCE( IDR_MENU ) );
hSubMenu = GetSubMenu( hMenu, 0 );
// disable all menu items, if specified
if( wParam & IDR_MENU_DISABLE )
{
wParam &= ~IDR_MENU_ENABLE_IDD_EXIT;
wParam |= IDR_MENU_DISABLE_IDD_RELOAD;
}
// enable the exit sub-menu item, if appropriate
if( wParam & IDR_MENU_ENABLE_IDD_EXIT )
{
uFlags = MF_BYCOMMAND | MF_ENABLED;
uIDItem = IDD_EXIT;
EnableMenuItem( hSubMenu, uIDItem, uFlags );
}
// disable the reload sub-menu item, if appropriate
if( wParam & IDR_MENU_DISABLE_IDD_RELOAD )
{
uFlags = MF_BYCOMMAND | MF_GRAYED;
uIDItem = IDD_RELOAD;
EnableMenuItem( hSubMenu, uIDItem, uFlags );
}
// assign the modified menu to the window
SetMenu( hWnd, hMenu );
return TRUE;
case WM_EXITTHREAD:
DestroyWindow( hWnd );
return TRUE;
case WM_DESTROY:
PostQuitMessage( 0 );
return FALSE;
case WM_CLOSE:
// do not really close, hide instead
ShowWindow( hWnd, SW_HIDE );
// also clear out the contents of the window
SetDlgItemText( hWnd, IDC_RICHEDIT, TEXT( "" ) ); // RW TEXT macro added
return TRUE;
case WM_COMMAND:
if( s_pSecdThrd && s_pSecdThrd->getMsgWnd() )
{
PostMessage( s_pSecdThrd->getMsgWnd(), msg, wParam, lParam );
}
return TRUE;
case WM_SIZE: // RW Added: track resizing of the window and call repaint
{
HWND hEdit = GetDlgItem( hWnd, IDC_RICHEDIT );
MoveWindow(hEdit, 0, 0,
LOWORD(lParam), // width of client area
HIWORD(lParam), // height of client area
TRUE); // repaint window
}
return TRUE;
case WM_SHOWTEXT:
{
char * pszText = (char *)lParam;
ShowWindow( hWnd, SW_SHOW );
CHARFORMAT chForm;
chForm.cbSize = sizeof(chForm);
chForm.dwMask = CFM_COLOR;
chForm.crTextColor =
wParam ? DARKRED : GetSysColor( COLOR_WINDOWTEXT );
chForm.dwEffects = 0;
HWND hEdit = GetDlgItem( hWnd, IDC_RICHEDIT );
int ndx = GetWindowTextLength( hEdit);
#ifdef WIN32
SendMessage( hEdit, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx );
#else
SendMessage( hEdit, EM_SETSEL, 0, MAKELONG( ndx, ndx ) );
#endif
//SendMessage( hEdit, EM_SETSEL, 0x7FFF, 0x7FFF );
SendMessage( hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &chForm );
#ifdef UNICODE
int size_needed = ::MultiByteToWideChar( CP_UTF8, 0, pszText, -1, NULL, 0 );
TCHAR * pszTextW = new TCHAR[ size_needed ];
::MultiByteToWideChar( CP_UTF8, 0, pszText, -1, pszTextW, size_needed );
SendMessage( hEdit, EM_REPLACESEL, FALSE, (LPARAM) pszTextW );
if ( pszTextW )
delete [] pszTextW;
#else
SendMessage( hEdit, EM_REPLACESEL, FALSE, (LPARAM)pszText );
#endif
//SendMessage( hEdit, EM_SETSEL, 0x7FFF, 0x7FFF );
SendMessage( hEdit, EM_SCROLLCARET, 0, 0 );
if ( pszText )
delete pszText;
}
return TRUE;
default:
return FALSE;
}
}
//---------------------------------------------------------------------------
// This is the main routine which the thread runs. It contains a windows
// message loop and will not return until the thread returns.
DWORD CALLBACK threadMain( void * pArg )
{
MessageWindow * pThis = (MessageWindow *)pArg;
// create a dialog box to display the messages
HINSTANCE hInstance = _Module.GetModuleInstance();
HWND hWnd = CreateDialogParam(
hInstance, // instance handle
MAKEINTRESOURCE( IDD_STDOUT ), // dialog box template
NULL, // parent window
dialogProc, // dialog box window proc
(LPARAM)pThis ); // parameter to pass
assert( hWnd );
pThis->setOutWnd( hWnd );
pThis->signalEvent();
if( hWnd == NULL )
{
return 1;
}
// enter a Windows message loop
MSG msg;
while( GetMessage( &msg, NULL, NULL, NULL ) )
{
if( !IsDialogMessage( hWnd, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return 0;
}
//---------------------------------------------------------------------------
MessageWindow::MessageWindow( DWORD dwFlags )
{
// create the thread we use to display messages; we use an event to make
// sure that the thread has started before continuing
m_hEvent = CreateEvent(
NULL, // security options
TRUE, // manual reset
FALSE, // not signaled
NULL ); // name
DWORD dwId;
m_hThread = CreateThread(
NULL, // security (use default)
0, // stack size (use default)
threadMain, // thread function
(void *)this, // argument for thread
0, // creation flags
&dwId ); // address for returned thread ID
assert( m_hThread != NULL );
if ( m_hEvent)
{
WaitForSingleObject( m_hEvent, 1000 );
CloseHandle( m_hEvent );
m_hEvent = NULL;
}
// update the window with the specified flags
updateWindow( dwFlags );
}
//---------------------------------------------------------------------------
MessageWindow::~MessageWindow()
{
// terminate the output window then wait for the thread to terminate
if( m_hOutWnd )
{
PostMessage( m_hOutWnd, WM_EXITTHREAD, 0, 0 );
m_hOutWnd = NULL;
}
if( m_hThread != NULL )
{
WaitForSingleObject( m_hThread, 1000 /*ms*/ );
m_hThread = NULL;
}
}
//---------------------------------------------------------------------------
void MessageWindow::displayText(const char * pszText, BOOL bError )
{
if( m_hOutWnd )
{
char * pszCopy = _strdup( pszText );
PostMessage( m_hOutWnd, WM_SHOWTEXT, bError, (LPARAM)pszCopy );
}
}
//---------------------------------------------------------------------------
void MessageWindow::updateWindow( DWORD dwFlags )
{
if( m_hOutWnd )
{
PostMessage( m_hOutWnd, WM_UPDATEWINDOW, dwFlags, 0 );
}
}