Thread View: borland.public.cppbuilder.nativeapi
19 messages
19 total messages
Started by Richard Casten
Thu, 23 Mar 2006 17:04
Length of text in MessageBox function
Author: Richard Casten
Date: Thu, 23 Mar 2006 17:04
Date: Thu, 23 Mar 2006 17:04
10 lines
1396 bytes
1396 bytes
I am going to be displaying an error message using the MessageBox function. As part of displaying the error message, I want to place an asterisk under the offending character. If I could find the length of any string in the font that is being used in the message box, I could figure out what the character position of the asterisk needs to be. It looks like the function GetTextExtentPoint32 would be the function to call, but I need to supply it a device context. How would I get the device context given that I am using the MessageBox function to display the text?
Re: Length of text in MessageBox function
Author: Remy Lebeau (TeamB)
Date: Thu, 23 Mar 2006 18:34
Date: Thu, 23 Mar 2006 18:34
28 lines
2161 bytes
2161 bytes
"Richard Casten" <richard.casten@aero.org> wrote in message news:4422D533.32E31292@aero.org... > If I could find the length of any string in the font that is > being used in the message box, I could figure out what > the character position of the asterisk needs to be. There isn't any native way to do that. The easiest thing to do is to just make your own dialog. Then you can calculate the length of the strings that you display. > How would I get the device context given that I am using > the MessageBox function to display the text? The only way to gain any kind of access to the MessageBox's internals is to install a hook via SetWindowsHookEx() for the calling thread before then calling MessageBox(). When the hook notifies your code that new windows are being created, you can check for the specific HWND of the text field, and then use GetWindowDC() to get its HDC. Even better, you can use this technique to manipulate the MessageBox() window itself in order to expand its dimensions, move its buttons around, add custom controls, etc. You could even hook the window procedure for the dialog and draw your asterik directly onto it, rather than manipulating the string to make an asterik fall into the desired location. Gambit
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Thu, 23 Mar 2006 19:43
Date: Thu, 23 Mar 2006 19:43
9 lines
1393 bytes
1393 bytes
"Remy Lebeau (TeamB)" wrote: > The only way to gain any kind of access to the MessageBox's internals is to > install a hook via SetWindowsHookEx() for the calling thread before then > calling MessageBox(). When the hook notifies your code that new windows are > being created, you can check for the specific HWND of the text field, and > then use GetWindowDC() to get its HDC. How would I know what is the specific HWND of the text field?
Re: Length of text in MessageBox function
Author: Remy Lebeau (TeamB)
Date: Thu, 23 Mar 2006 21:57
Date: Thu, 23 Mar 2006 21:57
24 lines
1695 bytes
1695 bytes
"Richard Casten" <richard.casten@aero.org> wrote in message
news:4422FA56.83B7F39@aero.org...
> How would I know what is the specific HWND of the text field?
Use an external window viewer, such as Spy++ or WinSight, to view the class
name for any HWND. For example, Spy++ shows the following on my machine for
the following code:
::MessageBox(NULL, "Test", "Testing", MB_OK);
00000844 "Testing" #32770 (Dialog)
|
--- 00000E54 "OK" Button
|
--- 00000A58 "Test" Static
The numbers are the memory addresses stored in the HWND handles. The
message box window has two child windows, one for the button and one for the
text. The class name of the text window is "Static".
Gambit
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Wed, 29 Mar 2006 19:23
Date: Wed, 29 Mar 2006 19:23
59 lines
2903 bytes
2903 bytes
"Remy Lebeau (TeamB)" wrote:
> "Richard Casten" <richard.casten@aero.org> wrote in message
> news:4422FA56.83B7F39@aero.org...
>
> > How would I know what is the specific HWND of the text field?
>
> The class name of the text window is "Static".
Thanks Remy. I am calling the SetWindowsHookEx function with idHook parameter
equal to WH_CALLWNDPROC right before I call MessageBox. In the hook function, I
test for the window having class name "Static". I am then trying to use the
DrawText function inside the hook function to draw a string. It is never
drawn. Is there a problem in using the DrawText function inside the hook
function?
This is the sample code: Only the input string to the MessageBox is drawn.
#include <windows.h>
LRESULT CALLBACK hook_proc(int nCode, WPARAM wParam, LPARAM lParam);
int main(int argc, char **argv)
{
HHOOK hook;
hook = SetWindowsHookEx(WH_CALLWNDPROC,hook_proc,NULL,
GetCurrentThreadId());
MessageBox(NULL,"First line of error\n","Error",MB_OK);
UnhookWindowsHookEx(hook);
return(0);
}
LRESULT CALLBACK hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
{
CWPSTRUCT *p;
char class_name[100];
HDC hdc;
RECT rect;
static char first=1;
char *second_line = "Second line of error";
if(nCode < 0)
return(CallNextHookEx(NULL,nCode,wParam,lParam));
p = (CWPSTRUCT *)lParam;
GetClassName(p->hwnd,class_name,sizeof(class_name));
if(first && stricmp(class_name,"Static") == 0)
{
hdc = GetDC(p->hwnd);
GetWindowRect(p->hwnd,&rect);
DrawText(hdc,second_line,strlen(second_line),&rect,
DT_SINGLELINE | DT_BOTTOM);
first = 0;
ReleaseDC(p->hwnd,hdc);
}
return(CallNextHookEx(NULL,nCode,wParam,lParam));
}
Re: Length of text in MessageBox function
Author: Remy Lebeau (TeamB)
Date: Wed, 29 Mar 2006 20:53
Date: Wed, 29 Mar 2006 20:53
27 lines
2132 bytes
2132 bytes
"Richard Casten" <richard.casten@aero.org> wrote in message news:442ADEA7.B11F561C@aero.org... > I am calling the SetWindowsHookEx function with idHook parameter > equal to WH_CALLWNDPROC right before I call MessageBox. I would not suggest using that particular hook type for this situation.WH_CBT would be more appropriate. > In the hook function, I test for the window having class name "Static". > I am then trying to use the DrawText function inside the hook function > to draw a string. I would not recommend that approach at all. Especially since you are not filtering the messages at all, so you are re-drawing on every possible message that the window receives. A better approach would be to resize both the "Dialog" itself and the "Static" window when it is created to accomodate the added size of your asterik. Then use SetWindowLong() to subclass the "Static" window's message procedure (or use a second hook) to do your asterik drawing only when the WM_PAINT message is actually received, after passing the WM_PAINT message to the default handler. Gambit
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Wed, 29 Mar 2006 22:53
Date: Wed, 29 Mar 2006 22:53
73 lines
3560 bytes
3560 bytes
"Remy Lebeau (TeamB)" wrote:
> A better approach would be to resize both the "Dialog" itself and the
> "Static" window when it is created to accomodate the added size of your
> asterik. Then use SetWindowLong() to subclass the "Static" window's message
> procedure (or use a second hook) to do your asterik drawing only when the
> WM_PAINT message is actually received, after passing the WM_PAINT message to
> the default handler.
I've tried your suggestion (assuming I've done it right) with the following
code, but I still do not get the second line of the message. Note: the window
will be the right height (I've checked) because of the "\n " at the end of the
first line string.
#include <windows.h>
LRESULT CALLBACK (*old_window_proc)(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM
lParam);
LRESULT CALLBACK new_window_proc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM
lParam);
LRESULT CALLBACK hook_proc(int nCode, WPARAM wParam, LPARAM lParam);
int main(int argc, char **argv)
{
HHOOK hook;
hook = SetWindowsHookEx(WH_CBT,hook_proc,NULL,GetCurrentThreadId());
MessageBox(NULL,"First line of error\n ","Error",MB_OK);
UnhookWindowsHookEx(hook);
return(0);
}
LRESULT CALLBACK hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
{
char class_name[100];
HWND hwnd;
if(nCode < 0)
return(CallNextHookEx(NULL,nCode,wParam,lParam));
if(nCode == HCBT_CREATEWND)
{
hwnd = (HWND)wParam;
GetClassName(hwnd,class_name,sizeof(class_name));
if(stricmp(class_name,"Static") == 0)
old_window_proc = (WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC,
(LONG)new_window_proc);
}
return(CallNextHookEx(NULL,nCode,wParam,lParam));
}
LRESULT CALLBACK new_window_proc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM
lParam)
{
char *second_line = "Second line of error";
RECT rect;
HDC hdc;
if(uMsg == WM_PAINT)
{
CallWindowProc(old_window_proc,hwnd,uMsg,wParam,lParam);
hdc = GetDC(hwnd);
GetWindowRect(hwnd,&rect);
DrawText(hdc,second_line,strlen(second_line),&rect,
DT_SINGLELINE | DT_BOTTOM);
ReleaseDC(hwnd,hdc);
SetWindowLong(hwnd,GWL_WNDPROC,(LONG)old_window_proc);
return(0);
}
return(CallWindowProc(old_window_proc,hwnd,uMsg,wParam,lParam));
}
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Thu, 30 Mar 2006 16:03
Date: Thu, 30 Mar 2006 16:03
40 lines
2393 bytes
2393 bytes
I realized I was using the position of the window within the parent window to
specify my drawing. I have now corrected it to this:
LRESULT CALLBACK new_window_proc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM
lParam)
{
char *second_line = "Second line of error";
RECT rect;
HDC hdc;
HFONT fnt,old_fnt;
int diff;
if(uMsg == WM_PAINT)
{
CallWindowProc(old_window_proc,hwnd,uMsg,wParam,lParam);
hdc = GetDC(hwnd);
GetWindowRect(hwnd,&rect);
diff = rect.bottom - rect.top;
rect.top = diff/2;
rect.bottom = diff + 1;
rect.left = 0;
rect.right = rect.right - rect.left + 1;
SetBkMode(hdc, TRANSPARENT);
fnt = GetStockObject(SYSTEM_FONT);
old_fnt = SelectObject(hdc,fnt);
DrawText(hdc,second_line,strlen(second_line),&rect,
DT_SINGLELINE | DT_BOTTOM | DT_INTERNAL);
SelectObject(hdc,old_fnt);
ReleaseDC(hwnd,hdc);
SetWindowLong(hwnd,GWL_WNDPROC,(LONG)old_window_proc);
return(0);
}
return(CallWindowProc(old_window_proc,hwnd,uMsg,wParam,lParam));
}
The second line is displayed but with a much larger font. How do I use the same
size font as the MessageBox font?
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Thu, 30 Mar 2006 17:05
Date: Thu, 30 Mar 2006 17:05
4 lines
1200 bytes
1200 bytes
I just realized that all I need to do is trap the WM_SETFONT message to get the font. Thanks for the suggestions Remy.
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Thu, 30 Mar 2006 18:34
Date: Thu, 30 Mar 2006 18:34
2 lines
1113 bytes
1113 bytes
One last thing (I hope). Is there any way to change the font of the message to be bold?
Re: Length of text in MessageBox function
Author: Remy Lebeau (TeamB)
Date: Thu, 30 Mar 2006 22:16
Date: Thu, 30 Mar 2006 22:16
12 lines
1447 bytes
1447 bytes
"Richard Casten" <richard.casten@aero.org> wrote in message news:442C24BE.8091C591@aero.org... > Is there any way to change the font of the message to be bold? You'll have to intercept and discard the original WM_SETFONT messages and then send your own message to the default handler specifyign your own HFONT handle. Gambit
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Thu, 30 Mar 2006 22:53
Date: Thu, 30 Mar 2006 22:53
12 lines
1759 bytes
1759 bytes
"Remy Lebeau (TeamB)" wrote: > You'll have to intercept and discard the original WM_SETFONT messages and > then send your own message to the default handler specifyign your own HFONT > handle. I was able to do and, as expected, the character string was clipped since the bold font produced a string longer than the window. I need to be able to resize the windows. I have tried to use SetWindowPos. It works for the parent window of the text but when I use it for the window containing the text, the text disappears. I was resizing when I received the WM_SETFONT message after changing the font.
Re: Length of text in MessageBox function
Author: Remy Lebeau (TeamB)
Date: Thu, 30 Mar 2006 23:17
Date: Thu, 30 Mar 2006 23:17
24 lines
2039 bytes
2039 bytes
"Richard Casten" <richard.casten@aero.org> wrote in message news:442C615F.2A382D1D@aero.org... > I was able to do and, as expected, the character string was clipped > since the bold font produced a string longer than the window. Did you apply your font before you resizes the windows? > I need to be able to resize the windows. I have tried to use SetWindowPos. > It works for the parent window of the text but when I use it for the window > containing the text, the text disappears. Please show your actual code. Changing a window's position should not effect its ability to display itself. Are you sure that you are not simply re-positioning offscreen? To be honest, at this point, your requirements are too complex for simple hooks. You would be better off just making your own dialog from scratch instead. Gambit
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Thu, 30 Mar 2006 23:39
Date: Thu, 30 Mar 2006 23:39
110 lines
4912 bytes
4912 bytes
Here is the code:
#include <windows.h>
LRESULT CALLBACK (*old_window_proc)(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM
lParam);
LRESULT CALLBACK new_window_proc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM
lParam);
LRESULT CALLBACK hook_proc(int nCode, WPARAM wParam, LPARAM lParam);
HWND hwnd;
int pos;
char *string = "Error in Repsat\n ";
int main(int argc, char **argv)
{
HHOOK hook;
pos = atoi(argv[1]);
hook = SetWindowsHookEx(WH_CBT,hook_proc,NULL,GetCurrentThreadId());
MessageBox(NULL,string,"Error",MB_OK);
SetWindowLong(hwnd,GWL_WNDPROC,(LONG)old_window_proc);
UnhookWindowsHookEx(hook);
return(0);
}
LRESULT CALLBACK hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
{
char class_name[100];
if(nCode < 0)
return(CallNextHookEx(NULL,nCode,wParam,lParam));
if(nCode == HCBT_CREATEWND)
{
hwnd = (HWND)wParam;
GetClassName(hwnd,class_name,sizeof(class_name));
if(stricmp(class_name,"Static") == 0)
old_window_proc = (WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC,
(LONG)new_window_proc);
}
return(0);
}
LRESULT CALLBACK new_window_proc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM
lParam)
{
SIZE size_string,size_character,size_asterisk;
RECT rect;
HDC hdc;
static HFONT fnt;
if(uMsg == WM_SETFONT)
{
LOGFONT lFont;
fnt = (HFONT)wParam;
hdc = GetDC(hwnd);
if (GetObject(fnt, sizeof(LOGFONT), (LPSTR) &lFont) != 0)
{
/* RESET TO BOLD */
lFont.lfWeight = FW_BOLD;
fnt = CreateFontIndirect(&lFont);
wParam = (WPARAM)fnt;
}
GetWindowRect(hwnd,&rect);
GetTextExtentPoint32(hdc,string,strlen(string),&size_string);
if(rect.right - rect.left + 1 < size_string.cx)
{
HWND hwnd_parent;
int diff;
diff = size_string.cx - (rect.right - rect.left + 1);
hwnd_parent = GetParent(hwnd);
GetWindowRect(hwnd_parent,&rect);
SetWindowPos(hwnd_parent,NULL,rect.left,rect.top,
rect.right - rect.left + 1 + diff,
rect.bottom - rect.top + 1,
SWP_NOZORDER | SWP_SHOWWINDOW);
GetWindowRect(hwnd,&rect);
SetWindowPos(hwnd,NULL,rect.left,rect.top,
rect.right - rect.left + 1 + diff,
rect.bottom - rect.top + 1,
SWP_NOZORDER | SWP_SHOWWINDOW);
}
}
else if(uMsg == WM_PAINT)
{
CallWindowProc(old_window_proc,hwnd,uMsg,wParam,lParam);
hdc = GetDC(hwnd);
SelectObject(hdc,(HGDIOBJ)(HFONT)fnt);
SetBkMode(hdc, TRANSPARENT);
GetWindowRect(hwnd,&rect);
GetTextExtentPoint32(hdc,string,pos-1,&size_string);
GetTextExtentPoint32(hdc,&string[pos-1],1,&size_character);
GetTextExtentPoint32(hdc,"*",1,&size_asterisk);
rect.right = rect.right - rect.left;
rect.bottom = rect.bottom - rect.top;
rect.left = size_string.cx +
(size_character.cx - size_asterisk.cx)/2;
rect.top = 0;
DrawText(hdc,"*",1,&rect,DT_SINGLELINE | DT_BOTTOM | DT_INTERNAL);
ReleaseDC(hwnd,hdc);
return(0);
}
return(CallWindowProc(old_window_proc,hwnd,uMsg,wParam,lParam));
}
Re: Length of text in MessageBox function
Author: Bob Gonder
Date: Fri, 31 Mar 2006 00:21
Date: Fri, 31 Mar 2006 00:21
9 lines
1576 bytes
1576 bytes
Richard Casten wrote: >I was able to do and, as expected, the character string was clipped since the >bold font produced a string longer than the window. You might try using TextOut() instead of DrawText() If that still clips, then maybe you could use the hdc of the parent window (dialog)
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Fri, 31 Mar 2006 19:59
Date: Fri, 31 Mar 2006 19:59
10 lines
1459 bytes
1459 bytes
Bob Gonder wrote: > You might try using TextOut() instead of DrawText() The same problem occurs with TextOut. > If that still clips, then maybe you could use the hdc of the parent > window (dialog) I tried doing that but it didn't seem to help. Thanks for the suggestions.
Re: Length of text in MessageBox function
Author: Mark Jacobs
Date: Tue, 04 Apr 2006 13:55
Date: Tue, 04 Apr 2006 13:55
23 lines
2107 bytes
2107 bytes
"Richard Casten" <richard.casten@aero.org> wrote in message news:442D8A1E.8012C74D@aero.org... > Bob Gonder wrote: > >> You might try using TextOut() instead of DrawText() > > The same problem occurs with TextOut. > >> If that still clips, then maybe you could use the hdc of the parent >> window (dialog) > > I tried doing that but it didn't seem to help. Thanks for the suggestions. > So, as you can see, it is easier to do your own modal dialog form to present your error message. It really isn't that hard to do. Design the form and put your components on it. Save it in a central library directory to your app dev env. Then, add the CPP file to each project that is going to use the form. -- Mark Jacobs DK Computing http://www.dkcomputing.co.uk
Re: Length of text in MessageBox function
Author: Richard Casten
Date: Tue, 04 Apr 2006 15:46
Date: Tue, 04 Apr 2006 15:46
10 lines
1931 bytes
1931 bytes
Mark Jacobs wrote: > So, as you can see, it is easier to do your own modal dialog form to present > your error message. It really isn't that hard to do. Design the form and put > your components on it. Save it in a central library directory to your app dev > env. Then, add the CPP file to each project that is going to use the form. I guess that's the right way to do it. However, I was trying to do this as pure 'C' function to go into our utility library and hence wanted to only use the Windows API. I know it would be easy if I used the VCL.
Re: Length of text in MessageBox function
Author: Bob Gonder
Date: Tue, 04 Apr 2006 17:24
Date: Tue, 04 Apr 2006 17:24
13 lines
1981 bytes
1981 bytes
Richard Casten wrote: >I guess that's the right way to do it. However, I was trying to do this as pure >'C' function to go into our utility library and hence wanted to only use the >Windows API. I know it would be easy if I used the VCL. There's no reason why you can't use the Win API to create a dialog. After all, people were creating windows dialogs for many years before VCL came along. The dialog resource just goes into an rc file. It's not a big deal. Use CreateDialog() to have full control over your dialog. Use DialogBox() if you only need standard handling.
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads