cancel
Showing results for 
Search instead for 
Did you mean: 
Subscribe

I'm using PB 11.5, in case that is relevant to the following.

So, response windows can't be resizable in PB, but I wanted them to be. I found a solution for that online somewhere (sorry, I seem to have lost the link). First you declare the following:

// Unicode declarations, - used to set Response windows to be resizable, which PB doesn't allow

function long GetWindowLongW (long hWindow, integer nIndex) Library "user32.dll" 

function long SetWindowLongW (long hWindow, integer nIndex, long dwNewLong) library "user32.dll"

The you call a function with the following code, in the window's Open event:

long        ll_Styles

n_cst_numerical lnv_num // PFC resize service

 

constant long WS_THICKFRAME = 262144

constant long WS_CAPTION = 12582912

constant long WS_SYSMENU = 524288 // N.B. This corresponds to ControlMenu in PB's General Window settings, it never seems to

               //        work for Response window, and in fact having ControlMenu checked on the actual

              //         Response window causes it to not be resizable!

/*

constant int SWP_NOSIZE = 1

constant int SWP_NOMOVE = 2

constant int SWP_NOZORDER = 4

constant int SWP_FRAMECHANGED = 32

*/

ll_styles = GetWindowLongW(handle(THIS), -16) 

if ll_styles <> 0 then 

    ll_styles = lnv_num.of_BitWiseOr(ll_styles, WS_THICKFRAME + WS_CAPTION)

   SetWindowLongW(handle(THIS), -16, ll_styles)

// According to the docs, calling the following is required after adding the WS_SYSMENU in SetWindowLong.

//     So I was hoping it would fix the fact that it makes the window non-rezisable. But it doesn't, unfortunately.

// SetWindowPos(handle(THIS), 0, 0, 0, 0, 0, SWP_FRAMECHANGED + SWP_NOMOVE + SWP_NOSIZE + SWP_NOZORDER)

end if

As you can perhaps see from my comments, there's a problem, which is that doing this doesn't work if Control Menu is checked in the window's painter (which is what puts the "X" at the top right, for closing the window). Adding in WS_SYSMENU to ll_styles should turn that back on, but it doesn't. (I can't immediately recall whether it does nothing, or also makes the window not be resizable.)

I don't suppose anybody has any bright ideas how to fix this? It's a bit weird in my app, which is mostly response windows, some of which are resizable and some of which aren't, that only the non-resizable ones have the control menu's "X".

Thanks.

0 Likes
View Entire Topic
Former Member
0 Likes

Here's what we use.  This is the of_setresizable function that takes an argument that determines whether or not a sizegrip should show at the bottom right corner of the window:

ulong     ll_style, hMenu, hWnd, ll_newstyle

hWnd = Handle( this )

 

//Turn on the instance variable that is used elsewhere to see if the window is resizeable

ib_resizeable = TRUE

 

//Get the original size of the window, which we will prevent the user from sizing the window

//less than

il_orig_width = this.width

il_orig_height = this.height

 

//Get the current window style

ll_style = GetWindowLong(handle(this), GWL_STYLE)

 

IF this.ControlMenu THEN

    //You have to include the MINIMIZEBOX attribute to get the controls to show

    ll_newstyle = ll_style + WS_THICKFRAME + WS_MINIMIZEBOX

ELSE

    ll_newstyle = ll_style + WS_THICKFRAME

END IF

 

IF ll_style <> 0 THEN

    IF SetWindowLong ( hWnd, GWL_STYLE, ll_newstyle ) <> 0 THEN

        IF this.ControlMenu THEN

            //Get a handle to the system menu

            hMenu = GetSystemMenu( hWnd, FALSE )

            IF hMenu > 0 THEN

                InsertMenu( hMenu, 1, MF_BYPOSITION + MF_STRING, &

                    SC_MAXIMIZE, "Maximize" ) ;

                InsertMenu( hMenu, 1, MF_BYPOSITION + MF_STRING, &

                    SC_RESTORE, "Restore" ) ;

                //The Size menu option has to be added to allow the resize gripper to work

                //if there is a control menu

                InsertMenu( hMenu, 1, MF_BYPOSITION + MF_STRING, &

                    SC_SIZE, "Size" ) ;

                DrawMenuBar( hWnd )

            END IF

        END IF

        //Force a repaint

        SetWindowPos ( hWnd, 0, 0, 0, 0, 0, &

            SWP_NOSIZE + SWP_NOMOVE + SWP_NOZORDER + SWP_FRAMECHANGED )

        this.SetRedraw( TRUE )

        //Track whether or not the size grip should show

        ib_show_szgrip = ab_showgrip

    END IF

END IF

We use this in an event mapped to pbm_getminmaxinfo:

//If this isn't a resizeable response window, don't bother with this

IF NOT ib_resizeable THEN RETURN

//Since we're resizable, we want to make sure that the user doesn't try to resize the

//window smaller than it's original size

s_MinMaxInfo lstr_MinMaxInfo

//Populate the structure

GetMinMaxInfo(lstr_MinMaxInfo, MinMaxInfo, 40)

//Determine the minimum size of the window (the original size)

lstr_MinMaxInfo.ptMinTrackSize.x = UnitsToPixels(il_orig_width, XUnitsToPixels!)

lstr_MinMaxInfo.ptMinTrackSize.y = UnitsToPixels(il_orig_height, YUnitsToPixels!)

//Now set the Min/Max info

SetMinMaxInfo(MinMaxInfo,lstr_MinMaxInfo,40)

return 0

Former Member
0 Likes

Bruce, I tried pretty much exactly your code, but first of all, although I have TitleBar checked in the painter for my window, unless I add in WS_CAPTION to the styles, the title bar disappears entirely. And even with it added in (and your code otherwise the same), I never get a control menu or "X" at the top right (which is what I really want).

The only other thing that might be different is I'm doing all this in an ancestor window of the actual window. (Maybe you were too and just didn't mention it.)

I will also study Chris' code that he pointed me at.

Former Member
0 Likes

That code is from our w_reponse window, the ancestor of all our response windows.  Works great for us.  I can only think you might have a constant value or external declaration wrong.

Did you see the comment in the code about about "You have to include the MINIMIZEBOX attribute to get the controls to show" and include that code?

Here's the constants we're using

CONSTANT int GWL_STYLE = -16

CONSTANT uint SWP_NOSIZE = 1

CONSTANT uint SWP_NOMOVE = 2

CONSTANT uint SWP_NOZORDER  = 4

CONSTANT uint SWP_FRAMECHANGED = 32

CONSTANT ulong WS_SYSMENU = 524288

CONSTANT ulong WS_THICKFRAME = 262144

CONSTANT ulong WS_MINIMIZEBOX = 65536

CONSTANT ulong WS_MAXIMIZEBOX = 131072

CONSTANT uint SC_RESTORE = 61728

CONSTANT uint SC_MAXIMIZE = 61488

CONSTANT uint SC_MINIMIZE = 61472

CONSTANT uint SC_SIZE = 61440

CONSTANT uint MF_BYCOMMAND = 0

CONSTANT uint MF_STRING = 0

CONSTANT uint MF_BYPOSITION = 1024

Former Member
0 Likes

Those are exactly the values I had, Bruce, with one exception: You seem to have swapped the values of WS_MINIMIZEBOX and WS_MAXIMIZEBOX, according to my copy of WinUser.h. So I tried using your value - no change in the behaviour. Without WS_CAPTION, there's no title bar, and with it, there's still no control menu or "X".

Here are my local external function declarations, in case you can see something wrong with them:

function long GetWindowLongW (long hWindow, integer nIndex) Library "user32.dll" 

function long SetWindowLongW (long hWindow, integer nIndex, long dwNewLong) library "user32.dll" 

function long SetWindowPos(long hWnd, long hWndInsertAfter, int newX, int newY, int newWidth, &

          int newHeight, uint uFlags) library "user32.dll"

function ulong GetSystemMenu(ulong hWnd, long bRevert) library "user32.dll"

function long InsertMenuW(uLong hMenu, uint uPosition, uint uFlags, uint uIDNewItem, String lpNewItem) library "user32.dll"

function long DrawMenuBar(ulong hWnd) library "user32.dll"

(Yes, I could use aliases to get rid of the "W" in the some of the function names, but obviously, that's not part of the problem.)

Former Member
0 Likes

I have some differences, though I don't know that they're material:

function boolean SetWindowPos(long hWnd, long hWndInsertAfter, int newX, int newY, int newWidth, &

          int newHeight, long uFlags) library "user32.dll"
function ulong GetSystemMenu(ulong hWnd, boolean bRevert) library "user32.dll"

function boolean InsertMenuW(uLong hMenu, uint uPosition, uint uFlags, uint uIDNewItem, String lpNewItem) library "user32.dll"

function boolean DrawMenuBar(ulong hWnd) library "user32.dll"

What probably is material is this:

IF this.ControlMenu THEN

          //You have to include the MINIMIZEBOX attribute to get the controls to show

          ll_newstyle = ll_style + WS_THICKFRAME + WS_MINIMIZEBOX

ELSE

          ll_newstyle = ll_style + WS_THICKFRAME

END IF

Since I've got the values of WS_MINIMIZEBOX and WS_MAXIMIZEBOX reversed, you probably want to change that to:

IF this.ControlMenu THEN

     //You have to include the MAXIMIZEBOX attribute to get the controls to show

     ll_newstyle = ll_style + WS_THICKFRAME + WS_MAXIMIZEBOX

ELSE

     ll_newstyle = ll_style + WS_THICKFRAME

END IF

Former Member
0 Likes

OK, Bruce, I finally figured out what was wrong. I was using a version of n_cst_numerical from the PFC to do the bitwise or-ing of the styles, whereas your code was just adding in the new styles.

When I tried just adding them in, your code worked perfectly.

When I dug into n_cst_numerical, the problem was that the of_BitwiseOr() function I was calling was expecting a long arg, and returning a long. When I looked at the current actual window styles value, pre-modification, it was not within the range of long values, but it was in the range of ulong values. When I hacked of_BitwiseOr to accept and return ulong values instead, it gave the same results as the simple addition in your code.

FWIW, Chris, your object that has similar functions for bitwise OR also uses longs, not ulongs, so presumably could run into the same problems if used on window styles. (Though perhaps there are other sensible uses where you would prefer to be working on signed longs.)

Just one remaining question - I really don't want the user to be able to maximize these windows, just size them a bit. (Largely because in almost all cases, I'm only sizing the main DW on the window vertically, not horizontally, so maximizing just puts in a lot of white space on the right.) So, any way to have this working, but remove the max box at the top right?

MANY THANKS!

Former Member
0 Likes

P.S. The following two lines don't seem to be required:

SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED + SWP_NOMOVE + SWP_NOSIZE + SWP_NOZORDER)

this.SetRedraw(TRUE)

Everything seems to work fine without them. Any reason to leave them in?

Former Member
0 Likes

Glad you got it resolved.

You could probably tweak the code in the GetMinMaxInfo event. What I have just makes sure they don't make the window too small.  You should be able to set the ptMaxTrackSize (like the current code sets the ptMinTrackSize) to prevent the window from being sized over a set limit.

Former Member
0 Likes

That forces a repaint of the window.  If it works fine for you without it, comment it out.  You can always uncomment it if you run into problems later.  It may only be required if you're using another control as a size grip (which we do).  Hard to tell at this point, I wrote that code back in 2004....

Former Member
0 Likes

If you dont want the Maximize button to show, remove or comment out the portion in red below.

It doesn't max a lot of sense to me why removing the WS_MINIMIZEBOX also removes the Maximize box.  But it seems to work.  The X still appears in the corner.

IF this.ControlMenu THEN

    //You have to include the MINIMIZEBOX attribute to get the controls to show

    ll_newstyle = ll_style + WS_THICKFRAME //+ WS_MINIMIZEBOX

ELSE

    ll_newstyle = ll_style + WS_THICKFRAME

END IF

Former Member
0 Likes

@ Bruce -

In your event mapped to pbm_getminmaxinfo - What are your external declarations for the GetMinMaxInfo and SetMinMaxInfo functions?

Maybe:

subroutine GetMinMaxInfo ( ref str_minmaxinfo d, long s, long l ) library 'kernel32.dll' alias for RtlMoveMemory

subroutine SetMinMaxInfo ( long d, str_minmaxinfo s, long l ) library 'kernel32.dll' alias for

RtlMoveMemory

Do they work on 64 bit machines?

Former Member
0 Likes

Actually, the point of that was to use the setting of the control menu on the window to determine whether the min/max buttons show.  Otherwise the IF doesn't serve a purpose with that code commented out.

That is, you don't need to comment out the code.  Just don't check the ControlMenu option in the window painter and you won't get the buttons.

Also note that my sample has the values for WS_MINIMIZEBOX and WS_MAXIMIZEBOX reversed.  That's why the code passes WS_MINIMIXEBOX here.

Former Member
0 Likes

Yes, that's exactly what they look like.

Works great on 64 bit.