FLTK sandbox

Check-in [bf99db0bbb]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:1) The Fl_Window::decorated_h() computation was incorrect under MSWindows10 because it did not use the correct dwmapi.dll - based implementation. This commit uses the correct way to compute the width and height of window borders in Fl_Window::decorated_h() and in Fl_Paged_Device::draw_decorated_window(). 2) Fixed the computation of enhanced metafile units that correspond to a given pixel size used by the Fl_Copy_Surface class on the WIN32 platform. Tested with MSWindows XP, 7 and 10 using the device test app. git-svn-id: http://seriss.com/public/fltk/fltk/branches/branch-1.3@10997 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:bf99db0bbb45722f5f45439723b1c1e2e6891803
User & Date: manolo@ea41ed52-d2ee-0310-a9c1-e6b18d33e121 2016-01-05 11:59:08
Context
2016-01-06
20:41
Fixed typo. git-svn-id: http://seriss.com/public/fltk/fltk/branches/branch-1.3@10998 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 check-in: d798ebc92a user: manolo@ea41ed52-d2ee-0310-a9c1-e6b18d33e121 tags: trunk
2016-01-05
11:59
1) The Fl_Window::decorated_h() computation was incorrect under MSWindows10 because it did not use the correct dwmapi.dll - based implementation. This commit uses the correct way to compute the width and height of window borders in Fl_Window::decorated_h() and in Fl_Paged_Device::draw_decorated_window(). 2) Fixed the computation of enhanced metafile units that correspond to a given pixel size used by the Fl_Copy_Surface class on the WIN32 platform. Tested with MSWindows XP, 7 and 10 using the device test app. git-svn-id: http://seriss.com/public/fltk/fltk/branches/branch-1.3@10997 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 check-in: bf99db0bbb user: manolo@ea41ed52-d2ee-0310-a9c1-e6b18d33e121 tags: trunk
05:48
1) For the X11 and the Mac OS platforms, a default font (FL_HELVETICA, FL_NORMAL_SIZE) is used when fl_draw() is called while no font has been set before. This commit does the same on the MSWindows platform, for consistency. 2) Slightly improved Fl_Image_Surface::draw_decorated_window() under WIN32. git-svn-id: http://seriss.com/public/fltk/fltk/branches/branch-1.3@10996 ea41ed52-d2ee-0310-a9c1-e6b18d33e121 check-in: 8fd80b6646 user: manolo@ea41ed52-d2ee-0310-a9c1-e6b18d33e121 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/Fl_Copy_Surface.cxx.

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  HDC hdc = GetDC(NULL);
  int hmm = GetDeviceCaps(hdc, HORZSIZE);
  int hdots = GetDeviceCaps(hdc, HORZRES);
  int vmm = GetDeviceCaps(hdc, VERTSIZE);
  int vdots = GetDeviceCaps(hdc, VERTRES);
  ReleaseDC(NULL, hdc);
  float factorw =  (100. * hmm) / hdots;
  float factorh =  (100. * vmm) / vdots + 0.5;
  
  RECT rect; rect.left = 0; rect.top = 0; rect.right = w * factorw; rect.bottom = h * factorh;
  gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL);
  if (gc != NULL) {
    SetTextAlign(gc, TA_BASELINE|TA_LEFT);
    SetBkMode(gc, TRANSPARENT);
  } 







|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  HDC hdc = GetDC(NULL);
  int hmm = GetDeviceCaps(hdc, HORZSIZE);
  int hdots = GetDeviceCaps(hdc, HORZRES);
  int vmm = GetDeviceCaps(hdc, VERTSIZE);
  int vdots = GetDeviceCaps(hdc, VERTRES);
  ReleaseDC(NULL, hdc);
  float factorw =  (100. * hmm) / hdots;
  float factorh =  (100. * vmm) / vdots;
  
  RECT rect; rect.left = 0; rect.top = 0; rect.right = w * factorw; rect.bottom = h * factorh;
  gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL);
  if (gc != NULL) {
    SetTextAlign(gc, TA_BASELINE|TA_LEFT);
    SetBkMode(gc, TRANSPARENT);
  } 

Changes to src/Fl_win32.cxx.

1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
....
2692
2693
2694
2695
2696
2697
2698
2699


























2700
2701
2702
2703
2704

2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740


2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754


2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769

2770
2771
2772
2773
2774
2775
2776
2777
....
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
      BOOL ok = AdjustWindowRectEx(&r, style, FALSE, styleEx);
      if (ok) {
        X = r.left;
        Y = r.top;
        W = r.right - r.left;
        H = r.bottom - r.top;
        bx = w->x() - r.left;
        by = r.bottom - w->y() - w->h(); // height of the bootm frame
        bt = w->y() - r.top - by; // height of top caption bar
        xoff = bx;
        yoff = by + bt;
        dx = W - w->w();
        dy = H - w->h();
        if (w_size_range_set && (w_maxw != w_minw || w_maxh != w_minh))
          ret = 2;
................................................................................
  return CreatePolygonRgn(pt, 4, ALTERNATE);
}

FL_EXPORT Window fl_xid_(const Fl_Window *w) {
  Fl_X *temp = Fl_X::i(w); 
  return temp ? temp->xid : 0;
}



























int Fl_Window::decorated_w()
{
  if (!shown() || parent() || !border() || !visible()) return w();
  int X, Y, bt, bx, by;
  Fl_X::fake_X_wm(this, X, Y, bt, bx, by);

  return w() + 2 * bx;
}

int Fl_Window::decorated_h()
{
  if (!shown() || parent() || !border() || !visible()) return h();
  int X, Y, bt, bx, by;
  Fl_X::fake_X_wm(this, X, Y, bt, bx, by);
  return h() + bt + 2 * by;
}

void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
{
  if (!win->shown() || win->parent() || !win->border() || !win->visible())
    print_widget(win, x_offset, y_offset);
  else
    draw_decorated_window(win, x_offset, y_offset, this);
}

void Fl_Paged_Device::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset, Fl_Surface_Device *toset)
{
  static HMODULE dwmapi_dll = LoadLibrary("dwmapi.dll");
  typedef HRESULT (WINAPI* DwmGetWindowAttribute_type)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
  static DwmGetWindowAttribute_type DwmGetWindowAttribute = 0;
  static const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
  int bt, bx, by; // compute the window border sizes
  RECT r;
  int need_r = 1;
  if (dwmapi_dll) {
    if (!DwmGetWindowAttribute) DwmGetWindowAttribute = (DwmGetWindowAttribute_type)GetProcAddress(dwmapi_dll, "DwmGetWindowAttribute");
    if (DwmGetWindowAttribute) {
      if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
        need_r = 0;
      }
    }
  }


  if (need_r) {
    GetWindowRect(fl_xid(win), &r);
  }
  bx = (r.right - r.left - win->w())/2;
  by = bx;
  bt = r.bottom - r.top - win->h() - 2*by;
  int ww = win->w() + 2 * bx;
  int wh = win->h() + bt + 2 * by;
  Fl_Display_Device::display_device()->set_current(); // make window current
  win->show();
  Fl::check();
  win->make_current();
  HDC save_gc = fl_gc;
  fl_gc = GetDC(NULL); // get the screen device context


  // capture the 4 window sides from screen
  Window save_win = fl_window;
  fl_window = NULL; // force use of read_win_rectangle() by fl_read_image()
  uchar *top_image = fl_read_image(NULL, r.left, r.top, ww, bt + by);
  uchar *left_image = bx ? fl_read_image(NULL, r.left, r.top, bx, wh) : NULL;
  uchar *right_image = bx ? fl_read_image(NULL, r.right - bx, r.top, bx, wh) : NULL;
  uchar *bottom_image = by ? fl_read_image(NULL, r.left, r.bottom-by, ww, by) : NULL;
  fl_window = save_win;
  ReleaseDC(NULL, fl_gc);  fl_gc = save_gc;
  toset->set_current();
  // print the 4 window sides
  fl_draw_image(top_image, x_offset, y_offset, ww, bt + by, 3); delete[] top_image;
  if (left_image) { fl_draw_image(left_image, x_offset, y_offset, bx, wh, 3); delete left_image; }
  if (right_image) { fl_draw_image(right_image, x_offset + win->w() + bx, y_offset, bx, wh, 3); delete right_image; }
  if (bottom_image) { fl_draw_image(bottom_image, x_offset, y_offset + win->h() + bt + by, ww, by, 3); delete bottom_image; }

  // print the window inner part
  this->print_widget(win, x_offset + bx, y_offset + bt + by);
}

#ifdef USE_PRINT_BUTTON
// to test the Fl_Printer class creating a "Print front window" button in a separate window
// contains also preparePrintFront call above
#include <FL/Fl_Printer.H>
................................................................................

#include <FL/Fl_Copy_Surface.H>
void copyFront(Fl_Widget *o, void *data)
{
  o->window()->hide();
  Fl_Window *win = Fl::first_window();
  if (!win) return;
  Fl_Copy_Surface *surf = new Fl_Copy_Surface(win->decorated_w() + 1, (int)(win->decorated_h() *0.985));
  surf->set_current();
  surf->draw_decorated_window(win); // draw the window content
  delete surf; // put the window on the clipboard
  Fl_Display_Device::display_device()->set_current();
  o->window()->show();
}








|







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


<
|
<
>





|
|
<





<
<
<
|




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
|
<
<
<
<
<
<
<
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|







 







|







1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
....
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727

2728

2729
2730
2731
2732
2733
2734
2735
2736

2737
2738
2739
2740
2741



2742
2743
2744
2745
2746















2747
2748
2749







2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
....
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
      BOOL ok = AdjustWindowRectEx(&r, style, FALSE, styleEx);
      if (ok) {
        X = r.left;
        Y = r.top;
        W = r.right - r.left;
        H = r.bottom - r.top;
        bx = w->x() - r.left;
        by = r.bottom - w->y() - w->h(); // height of the bottom frame
        bt = w->y() - r.top - by; // height of top caption bar
        xoff = bx;
        yoff = by + bt;
        dx = W - w->w();
        dy = H - w->h();
        if (w_size_range_set && (w_maxw != w_minw || w_maxh != w_minh))
          ret = 2;
................................................................................
  return CreatePolygonRgn(pt, 4, ALTERNATE);
}

FL_EXPORT Window fl_xid_(const Fl_Window *w) {
  Fl_X *temp = Fl_X::i(w); 
  return temp ? temp->xid : 0;
}

static RECT border_width_title_bar_height(Fl_Window *win, int &bx, int &by, int &bt)
{
  RECT r = {0,0,0,0};
  bx = by = bt = 0;
  if (win->shown() && !win->parent() && win->border() && win->visible()) {
    static HMODULE dwmapi_dll = LoadLibrary("dwmapi.dll");
    typedef HRESULT (WINAPI* DwmGetWindowAttribute_type)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
    static DwmGetWindowAttribute_type DwmGetWindowAttribute = dwmapi_dll ?
    (DwmGetWindowAttribute_type)GetProcAddress(dwmapi_dll, "DwmGetWindowAttribute") : NULL;
    int need_r = 1;
    if (DwmGetWindowAttribute) {
      const DWORD DWMWA_EXTENDED_FRAME_BOUNDS = 9;
      if ( DwmGetWindowAttribute(fl_xid(win), DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK ) {
        need_r = 0;
      }
    }
    if (need_r) {
      GetWindowRect(fl_xid(win), &r);
    }
    bx = (r.right - r.left - win->w())/2;
    by = bx;
    bt = r.bottom - r.top - win->h() - 2*by;
  }
  return r;
}

int Fl_Window::decorated_w()
{

  int bt, bx, by;

  border_width_title_bar_height(this, bx, by, bt);
  return w() + 2 * bx;
}

int Fl_Window::decorated_h()
{
  int bt, bx, by;
  border_width_title_bar_height(this, bx, by, bt);

  return h() + bt + 2 * by;
}

void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset)
{



  draw_decorated_window(win, x_offset, y_offset, this);
}

void Fl_Paged_Device::draw_decorated_window(Fl_Window *win, int x_offset, int y_offset, Fl_Surface_Device *toset)
{















  int bt, bx, by; // border width and title bar height of window
  RECT r = border_width_title_bar_height(win, bx, by, bt);
  if (bt) {







    Fl_Display_Device::display_device()->set_current(); // make window current
    win->show();
    Fl::check();
    win->make_current();
    HDC save_gc = fl_gc;
    fl_gc = GetDC(NULL); // get the screen device context
    int ww = win->w() + 2 * bx;
    int wh = win->h() + bt + 2 * by;
    // capture the 4 window sides from screen
    Window save_win = fl_window;
    fl_window = NULL; // force use of read_win_rectangle() by fl_read_image()
    uchar *top_image = fl_read_image(NULL, r.left, r.top, ww, bt + by);
    uchar *left_image = bx ? fl_read_image(NULL, r.left, r.top, bx, wh) : NULL;
    uchar *right_image = bx ? fl_read_image(NULL, r.right - bx, r.top, bx, wh) : NULL;
    uchar *bottom_image = by ? fl_read_image(NULL, r.left, r.bottom-by, ww, by) : NULL;
    fl_window = save_win;
    ReleaseDC(NULL, fl_gc);  fl_gc = save_gc;
    toset->set_current();
    // draw the 4 window sides
    fl_draw_image(top_image, x_offset, y_offset, ww, bt + by, 3); delete[] top_image;
    if (left_image) { fl_draw_image(left_image, x_offset, y_offset, bx, wh, 3); delete left_image; }
    if (right_image) { fl_draw_image(right_image, x_offset + win->w() + bx, y_offset, bx, wh, 3); delete right_image; }
    if (bottom_image) { fl_draw_image(bottom_image, x_offset, y_offset + win->h() + bt + by, ww, by, 3); delete bottom_image; }
  }
  // draw the window inner part
  this->print_widget(win, x_offset + bx, y_offset + bt + by);
}

#ifdef USE_PRINT_BUTTON
// to test the Fl_Printer class creating a "Print front window" button in a separate window
// contains also preparePrintFront call above
#include <FL/Fl_Printer.H>
................................................................................

#include <FL/Fl_Copy_Surface.H>
void copyFront(Fl_Widget *o, void *data)
{
  o->window()->hide();
  Fl_Window *win = Fl::first_window();
  if (!win) return;
  Fl_Copy_Surface *surf = new Fl_Copy_Surface(win->decorated_w(), win->decorated_h());
  surf->set_current();
  surf->draw_decorated_window(win); // draw the window content
  delete surf; // put the window on the clipboard
  Fl_Display_Device::display_device()->set_current();
  o->window()->show();
}