• Welcome to Jose's Read Only Forum 2023.
 

Possible Bug In VC19

Started by Frederick J. Harris, November 19, 2016, 05:09:19 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Frederick J. Harris

Hi James,

I worked on it several hours today and it appears the VC19 built window is getting truncated to the tune of several pixels.  If you compare two windows side by side from VC19 and anything else the VC19 window is noticeably less in height.  Also, I realized MS keeps adding metrics to GetSystemMetrics.  I'm attaching my work from today.  It is the same app as your code.  I put piles of output log statements in a version to output the system metrics of piles of stuff.  Compare "Output_VC9.txt" to "Output_VC15.txt".  The only difference you'll see is ...

iCxPaddedBorder

...which is gotten through SM_CXPADDEDBORDER.  It comes out as 0 for VC9 and 4 for VC19.  Also, the caption/title bar is larger on VC19 even though GetSystemMetrics is showing no change between compilers.  Its time for me to go to bed but it would be interesting to output GetWindowRect() values between a VC19 window and anything else.  Attached is my app that generated those output files.  I tested with #define TCLib and #define Debug.  You'll be able to figure out what to do.  'till tomorrow.

Fred

PS - gmail won't let me send zip.  I'll post in Jose's Forum

Patrice Terrier

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

Fred,
VC9??

I tried with c++ cl 18. and it was the same as cl 19.
I do not have any older version to try.

James

Frederick J. Harris

Quote
VC9??

I know the version numbers MS uses are confusing.  My Visual Studio 2008 actually installs its C/C++ files in a directory VC9.  However, if you look at the compiler version output during a typical command line compile, it states VC15.  So there are three somewhat unrelated numbers there.

With Visual Studio Community 2015 the the compiler version number output during a compile is 19!

I just saw your reply Patrice.  Thanks for that info.  Like James I wasn't familiar with that function.  What I was thinking one must do would be to use all the different values returned by GetSystemMetrics() to kind of 'back calculate' what the parameters of the CreateWindowEx() call should be for a specific Client Rectangle.  But that 'Adjust' function does it for you.

For me, I'm not very enamored of Visual Studio Community 2015.  I sweat blood for a week last winter due to a documented compiler bug when I was doing my TCLib work.  The documented bug had to do with Microsoft's attempt to create something like PowerBASIC's Dim At for Classes.   The C++ standard keeps changing, as its user base seems to want to morph it into C#, seems to me.   


James C. Fuller


I'm going to do this (thanks to José Roca's AfxWin). Use zeros for width and height and then call this.
Can also be used for dpi aware app's.
I'd still would like to know what is going on!!
James


void    SetClientSize (HWND, long, int, float = 1, float = 1);

void SetClientSize (HWND hwnd, long nWidth, int nHeight, float rxRatio, float ryRatio)
{
    RECT     rc = {0};
    RECT     rcTemp = {0};
    // Convert the client rectangle to a window rectangle.
    // The AdjustWindowRectEx function cannot take menu wrapping into account
    // because it doesn't know which menu we are using.
    SetRect( &rc, 0, 0, nWidth * rxRatio, nHeight * ryRatio);
    HANDLE   hMenu = GetMenu(hwnd);
    DWORD    dwStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
    AdjustWindowRectEx( &rc, dwStyle, (hMenu != NULL), GetWindowLongPtr(hwnd, GWL_EXSTYLE));

    // If there is a menu, we need to check how much wrapping occurs when we set
    // the window to the width specified by AdjustWindowRectEX and an infinite
    // amount of height. An infinite height allows us to see every single menu wrap.

    if(hMenu != NULL )
    {
        rcTemp = rc;
        rcTemp.bottom = 0x7FFF; // "Infinite" height
        SendMessage(hwnd, (UINT)WM_NCCALCSIZE, (WPARAM)0, (LPARAM)&rcTemp);
        // Adjust our previous calculation to compensate for menu wrapping.
        rc.bottom +=   rcTemp.top;
    }

    // The AdjustWindowRectEx function does not take the WS_VSCROLL or WS_HSCROLL
    // styles into account. To account for the scroll bars, we need to call the
    // GetSystemMetrics function with SM_CXVSCROLL or SM_CYHSCROLL.

    if((dwStyle & WS_HSCROLL) == WS_HSCROLL )
    {
        rc.bottom = rc.bottom + GetSystemMetrics( SM_CYHSCROLL);
    }
    if((dwStyle & WS_VSCROLL) == WS_VSCROLL )
    {
        rc.right = rc.right + GetSystemMetrics( SM_CXVSCROLL);
    }
    long     cx = rc.right - rc.left;
    long     cy = rc.bottom - rc.top;
    SetWindowPos(hwnd, NULL, 0, 0, cx, cy, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
}



Frederick J. Harris

I worked on it some more Jim, as I found the whole thing curious, but I had to get back to my work.  There are several things I'm not sure about.

For one, I find it curious that two different versions of Visual Studio (my VStudio 2008 and VStudio 2015) create graphical components with different metrics on the same operating system and same computer.  I was using a Win 10 Home HP Envy laptop.  And of course I have both versions of Visual Studio installed on that box.  I guess both have the SDK installed/available that came with each respective version, and with each version would also have the necessary *.lib files.  I can see how those might be different, but they are each linking with the same basic dlls not?  That is, gdi32.dll???  As one of the respondents at CodeGuru mentioned, there must be something going on with manifests or calls to the dlls to tell them to react different for one call from another.

Another thing I find strange is that when you compare the windows side by side the title bars are obviously of a different height.  I mean, its visually not even a close call.  On the VS2015 the title bar is unmistakingly deeper.  Yet the calls to GetSystemMetrics to retrieve that height reveals them the same for both windows.  I was able to piece everything together in terms of sizes with GetSystemMetrics calls for my VS 2008 windows, but not for the VS2015 windows.

In any case, the code Patrice and Jose provided seems to resolve the issue, so I don't know if there is any more point in wondering about it.

Patrice Terrier

The answer is quite obvious, Visual Studio 2015 uses the latest SDK (the one from Windows 8+ 10)
while 2008 version uses the older SDK.

There are many new API starting with the SDK for Windows 8+, and of course they are not available with previous SDK build.
For example the touchscreen API is much simpler with the latest SDK.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

Patrice,
  Yes different SDK's but they are all accessing the same User32.dll ?

I did a loadlibray and still got the same results???

James


typedef HWND (__stdcall *BCXFPROT1)(DWORD, LPCSTR, LPCSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID);

// **********[ DLL Declarations ]**********

    HMODULE  H_USER32 = LoadLibrary("User32.dll");
    if(H_USER32 == NULL) {
        MessageBox (GetActiveWindow(), "Failed to load library \nUser32.dll", "Load Library Error", 0 );
        return 1;
    }
    bc9CreateWindow = (BCXFPROT1)GetProcAddress(H_USER32, "CreateWindowExA");
    if(bc9CreateWindow == NULL) {
        MessageBox (GetActiveWindow(), "Failed to find process \nbc9CreateWindow", "Find Process Error", 0 );
        return 1;
    }

// ****************************************

hWin = bc9CreateWindow( dwStyleEx, szClassName, "What is your name? ", dwStyle, ( GetSystemMetrics( SM_CXSCREEN) - 246) / 2, ( GetSystemMetrics( SM_CYSCREEN) - 110) / 2, 246, 110, 0, 0, hInst, NULL);

James C. Fuller

Patrice,
  It is not a Win 8.1 10 sdk thing.
It fails with the VS 2012 express also.

James

Patrice Terrier

#9
I never had such problem when using AdjustWindowrRect, with 2010 (Pro), 2013 (Pro) , 2015 (Community),
and same with PB 9.05 and PB 10.04.

AdjustWindowRect has always served me well, since the first version of my WinLIFT skin engine long ago.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Frederick J. Harris

Quote
It fails with the VS 2012 express also.

Its working for you now with AdjustWindowRectEx() isn't it?

James C. Fuller

Patrice,
  I did not mean your solution I meant my original failing code.
All works fine with both your's and José's solutions.
I am just trying to figure out why my original code fails and where the changes are documented. Fred said the original code worked fine with vs 2008. What changed and where is it documented?
James

Frederick J. Harris

Maybe Patrice or Jose know where its documented, and maybe not.  I sure don't.

All the way back to my first coding of Windows with Windows 95 every new version of Windows changed the metrics of the various constituents of a window, e.g., the size of the title bar, the thickness of borders, etc.  And it just came to my attention in fooling around with this that the numbers of the various equates passed into GetSystemMetrics() keeps growing as things become more complicated.  I always figurred that if one needed to code an app at a high level of generalization (works on everything) one would have to make calls to all those GetSystemMetrics() values and code accordingly.  I guess that's why in trying to understand this I tried to understand it through the GetSystemMetrics() function figuring that one could find the differences there.  I couldn't quite piece it all together though for VS 2015.  Maybe if I worked harder and longer at it.  But if AdjustWindowRectEx() or AdjustWindowRect() takes care of it anyway, I'm not certain its worth the trouble.  After all we're kind of talking about proprietary stuff internal to Windows here.

José Roca

#13
AdjustWindowRect calls AdjustWindowRectEx passing 0 as the extended style:


BOOL WINAPI DECLSPEC_HOTPATCH AdjustWindowRect  (  LPRECT   lpRect,
      DWORD    dwStyle,
      BOOL     bMenu
   ) 
   
   {
   return AdjustWindowRectEx(lpRect, dwStyle, bMenu, 0);
}


AdjustWindowRextEx checks if the window is hooked and, if it is not, calls an internal function called RealAdjustWindowRectEx:


BOOL WINAPI DECLSPEC_HOTPATCH AdjustWindowRectEx   (  LPRECT   lpRect,
      DWORD    dwStyle,
      BOOL     bMenu,
      DWORD    dwExStyle
   ) 
   
   {
   BOOL Hook, Ret = FALSE;

   LoadUserApiHook();

   Hook = BeginIfHookedUserApiHook();

     /* Bypass SEH and go direct. */
   if (!Hook) return RealAdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);

   _SEH2_TRY
   {
      Ret = guah.AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
   }
   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
   {
   }
   _SEH2_END;

   EndUserApiHook();

   return Ret;
}


And this is the RealAdjustWindowRectEx function:


BOOL WINAPI RealAdjustWindowRectEx  (  LPRECT   lpRect,
      DWORD    dwStyle,
      BOOL     bMenu,
      DWORD    dwExStyle
   ) 
   
   {
   SIZE BorderSize;

   if (bMenu)
   {
      lpRect->top -= GetSystemMetrics(SM_CYMENU);
     }
     if ((dwStyle & WS_CAPTION) == WS_CAPTION)
     {
        if (dwExStyle & WS_EX_TOOLWINDOW)
           lpRect->top -= GetSystemMetrics(SM_CYSMCAPTION);
        else
           lpRect->top -= GetSystemMetrics(SM_CYCAPTION);
     }
     UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
     InflateRect(
        lpRect,
        BorderSize.cx,
        BorderSize.cy);
 
     return TRUE;
  }


And the UserGetWindowBorders procedure called by RealAdjustWindowRectEx:


VOID UserGetWindowBorders  (  DWORD    Style,
      DWORD    ExStyle,
      SIZE *   Size,
      BOOL     WithClient
   ) 
   
   {
   DWORD Border = 0;

   if (UserHasWindowEdge(Style, ExStyle))
      Border += 2;
   else if (ExStyle & WS_EX_STATICEDGE)
      Border += 1;
   if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
      Border += 2;
   if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
      Border ++;
   Size->cx = Size->cy = Border;
   if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
   {
      Size->cx += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
      Size->cy += GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
   }
   Size->cx *= GetSystemMetrics(SM_CXBORDER);
   Size->cy *= GetSystemMetrics(SM_CYBORDER);
}


What I don't know is if this code is still being used as is by the newest Windows versions or if they have changed it.

José Roca

Because I was tired of seeing the size of the client window to change with each version of Windows, because of different sizes of gui elements such the caption, I wrote the function AfxSetWindowClientSize that is a wraper for AdjustWindowRectEx, but also taking into account possible menu wrapping and the WS_VSCROLL and WS_HSCROLL styles. I borrowed the code for menu wrapping from somewhere.