mirror of
https://github.com/fltk/fltk.git
synced 2026-06-05 16:12:13 +08:00
STR#2086 related Fixes :
This one was really tough to track, understand: In fact, the problem was comming from the misplacement of the menu window, which itself came from invalid measurement, which itself came from invalid fl_witdh() measurement, but only when fl_gc is not valid because fl_width() relies on Win32 on the call of GetTextExtentPoint32W which can't succeed if the HDC(here fl_gc) is not valid ! Now the fix: A best-effort algorithm has been furthered to supply a valid fltk hdc if we can have one or a screen hdc if no fltk window is found by fl::first_window(). Note that when fl_gc is NULL inside fl_width() call, it can happen that Fl_Window::current() is not null but invalid (already deleted). Finally, in the case of the buggy menu window observed here, this fl_gc was set to NULL just after an Fl_Menu_Window deletion and re-creation in Fl_Menu_Item::pulldown(). Also added a comment to describe the new fl_width() behavior. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@6540 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
+6
-5
@@ -80,7 +80,7 @@ const Fl_Menu_Item* Fl_Menu_Item::next(int n) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// appearance of current menus are pulled from this parent widget:
|
// appearance of current menus are pulled from this parent widget:
|
||||||
static const Fl_Menu_* button;
|
static const Fl_Menu_* button=0;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -320,7 +320,8 @@ menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp,
|
|||||||
if (t) Wtitle = t->measure(&Htitle, button) + 12;
|
if (t) Wtitle = t->measure(&Htitle, button) + 12;
|
||||||
int W = 0;
|
int W = 0;
|
||||||
if (m) for (; m->text; m = m->next()) {
|
if (m) for (; m->text; m = m->next()) {
|
||||||
int hh; int w1 = m->measure(&hh, button);
|
int hh;
|
||||||
|
int w1 = m->measure(&hh, button);
|
||||||
if (hh+LEADING>itemheight) itemheight = hh+LEADING;
|
if (hh+LEADING>itemheight) itemheight = hh+LEADING;
|
||||||
if (m->flags&(FL_SUBMENU|FL_SUBMENU_POINTER)) w1 += 14;
|
if (m->flags&(FL_SUBMENU|FL_SUBMENU_POINTER)) w1 += 14;
|
||||||
if (w1 > W) W = w1;
|
if (w1 > W) W = w1;
|
||||||
@@ -541,7 +542,7 @@ struct menustate {
|
|||||||
menuwindow* fakemenu; // kludge for buttons in menubar
|
menuwindow* fakemenu; // kludge for buttons in menubar
|
||||||
int is_inside(int mx, int my);
|
int is_inside(int mx, int my);
|
||||||
};
|
};
|
||||||
static menustate* p;
|
static menustate* p=0;
|
||||||
|
|
||||||
// return 1 if the coordinates are inside any of the menuwindows
|
// return 1 if the coordinates are inside any of the menuwindows
|
||||||
int menustate::is_inside(int mx, int my) {
|
int menustate::is_inside(int mx, int my) {
|
||||||
@@ -826,7 +827,7 @@ const Fl_Menu_Item* Fl_Menu_Item::pulldown(
|
|||||||
if (pp.current_item == oldi) continue;}
|
if (pp.current_item == oldi) continue;}
|
||||||
// only do rest if item changes:
|
// only do rest if item changes:
|
||||||
|
|
||||||
delete pp.fakemenu; pp.fakemenu = 0; // turn off "menubar button"
|
if(pp.fakemenu) {delete pp.fakemenu; pp.fakemenu = 0;} // turn off "menubar button"
|
||||||
|
|
||||||
if (!pp.current_item) { // pointing at nothing
|
if (!pp.current_item) { // pointing at nothing
|
||||||
// turn off selection in deepest menu, but don't erase other menus:
|
// turn off selection in deepest menu, but don't erase other menus:
|
||||||
@@ -834,7 +835,7 @@ const Fl_Menu_Item* Fl_Menu_Item::pulldown(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pp.fakemenu; pp.fakemenu = 0;
|
if(pp.fakemenu) {delete pp.fakemenu; pp.fakemenu = 0;}
|
||||||
initial_item = 0; // stop the startup code
|
initial_item = 0; // stop the startup code
|
||||||
pp.p[pp.menu_number]->autoscroll(pp.item_number);
|
pp.p[pp.menu_number]->autoscroll(pp.item_number);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -368,7 +368,7 @@ void fl_measure(const char* str, int& w, int& h, int draw_symbols) {
|
|||||||
char buf[MAXBUF];
|
char buf[MAXBUF];
|
||||||
int buflen;
|
int buflen;
|
||||||
int lines;
|
int lines;
|
||||||
double width;
|
double width=0;
|
||||||
int W = 0;
|
int W = 0;
|
||||||
char symbol[2][255], *symptr;
|
char symbol[2][255], *symptr;
|
||||||
int symwidth[2], symtotal;
|
int symwidth[2], symtotal;
|
||||||
|
|||||||
@@ -26,7 +26,9 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
# define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
/* We require Windows 2000 features such as GetGlyphIndices */
|
/* We require Windows 2000 features such as GetGlyphIndices */
|
||||||
# if !defined(WINVER) || (WINVER < 0x0500)
|
# if !defined(WINVER) || (WINVER < 0x0500)
|
||||||
# define WINVER 0x0500
|
# define WINVER 0x0500
|
||||||
|
|||||||
+14
-1
@@ -182,11 +182,24 @@ double fl_width(unsigned int c) {
|
|||||||
fl_fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400);
|
fl_fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400);
|
||||||
SIZE s;
|
SIZE s;
|
||||||
unsigned short i = 0, ii = r * 0x400;
|
unsigned short i = 0, ii = r * 0x400;
|
||||||
|
// The following code is a best effort algorithm to further a valid fl_gc
|
||||||
|
// if no fl_gc is available at the time we call fl_width()
|
||||||
|
// We first choose a gc from the first fltk window,
|
||||||
|
// if it is null then the gc from the current screen (GetDC(NULL)).
|
||||||
|
// This should solve STR #2086
|
||||||
|
HDC gc = fl_gc;
|
||||||
|
HWND hWnd = 0;
|
||||||
|
if (!gc) {
|
||||||
|
gc = GetDC(hWnd);
|
||||||
|
}
|
||||||
|
if (!gc)
|
||||||
|
Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!");
|
||||||
for (; i < 0x400; i++) {
|
for (; i < 0x400; i++) {
|
||||||
GetTextExtentPoint32W(fl_gc, (WCHAR*)&ii, 1, &s);
|
GetTextExtentPoint32W(gc, (WCHAR*)&ii, 1, &s);
|
||||||
fl_fontsize->width[r][i] = s.cx;
|
fl_fontsize->width[r][i] = s.cx;
|
||||||
ii++;
|
ii++;
|
||||||
}
|
}
|
||||||
|
if (gc && gc!=fl_gc) ReleaseDC(hWnd, gc);
|
||||||
}
|
}
|
||||||
return (double) fl_fontsize->width[r][c & 0x03FF];
|
return (double) fl_fontsize->width[r][c & 0x03FF];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user