News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

How do I change borders as desired after window is already created?

Started by jimg, March 24, 2018, 09:35:06 AM

Previous topic - Next topic

jimg

I'm having a problem trying to set the border style at execution time.

If I create the window with an exstyle, it sets the border properly, but if I create the window without the exstyle and try to add it later using SetWindowLong, it doesn't apply the correct border.

For this test, I am starting with the WS_BORDER style (thin border) and applying every possible exstyle I have found.

If you run the program, the column on the left is created with CreateWindowEx with the exstyle set.  The column on the right is created with CreateWindowEx but with zero for the exstyle, and the exstyle is applied later with SetWindowLong.

Anyone have any ideas how to get this to work so I can let the user change to the border style he prefers?

Some example code:
wStyle dd WS_POPUP or WS_CLIPSIBLINGS or WS_HSCROLL or WS_VSCROLL or \
    WS_VISIBLE or ES_MULTILINE or ES_NOHIDESEL or\
    ES_SAVESEL or ES_WANTRETURN or ES_AUTOHSCROLL or ES_AUTOVSCROLL or \
    WS_BORDER
.code
    inv CreateWindowEx, WS_EX_APPWINDOW,soff("RichEdit20A"),soff("Bordertest"),
           wStyle, rl,rt,rx,ry, 0, 0, hWin, 0

    mov eStyle,WS_EX_APPWINDOW or WS_EX_CLIENTEDGE
    inv SetWindowLong,hEdit,GWL_EXSTYLE,eStyle
    inv SetWindowPos,hEdit,0,rl,rt,rx,ry,SWP_FRAMECHANGED ; required


It may seem odd to combine these two, but I've found nine distinct border styles of of the twenty possible combinations.


fearless

I recall something about calling SetWindowPos with SWP_FRAMECHANGED

QuoteApplies new frame styles set using the SetWindowLong function

So might have to call that afterwards to force the update of the style to be properly "seen" by the internal windows stuff.


jimg

I feel like I'm in the twilight zone.  What am I missing here?

The last line of my above message contained that.

The sample program I attached did that.

What are you guys trying to tell me?

jj2007

 :biggrin:

Sorry, Jim, I was so fascinated of the idea to change borders on the fly that I opened one of my templates and started to code without even opening your version, or reading thoroughly your post. Apologies :icon_redface:

Now I went through your code but didn't quite understand what it does. You are creating five windows to the left, then five to the right with identical styles. Afterwards, you try to change the styles of those in the right column. Is that correct?

One thing I noticed is that you use a richedit control for testing. Perhaps that is alright, perhaps not - it is a buggy beast, as we all know, and not all styles or style changes may work with it. My sample worked on the main window only, which is again different; and I was really surprised that it is possible to change from WS_BORDER to WS_THICKFRAME and back 8)

Btw SetWindowPos is not required to apply the style:
jinvoke InvalidateRect, hWnd, 0, 1
; jinvoke SetWindowPos, hWnd, HWND_TOPMOST, 300+320*@64, 127, 300, 200, SWP_FRAMECHANGED or SWP_NOMOVE or SWP_NOSIZE


This works, too, but you see the changed borders only when sizing the window.

avcaballero

Changing the window style is a pain. I looked for this subject some time ago. What I have collected is that the window caches and it is needed to use the SetWindowPos to obligate to recache and even hide the window before trying to change it. After several tries I concluded that there's no good way to get it working. So perhaps the better way is using a flat window and paint your own frames that you can change whatever you want.

I attach a proove with no much success.

What it can be done without much effort is modifying the objects in the title bar.

Siekmanski

Hi Jim,

Don't know for sure if this is what your looking for...
I use this to change the window styles to toggle between windowed and full screens.

ToggleFullScreen proc

    .if (!m_Windowed)
        mov         m_Windowed,TRUE
        invoke      SetWindowLong,hWnd,GWL_EXSTYLE,WS_EX_CLIENTEDGE
        invoke      SetWindowLong,hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW
        invoke      SetWindowLong,hWnd,GWL_WNDPROC,WndProc_ptr
        mov         eax,WindowRect.right
        sub         eax,WindowRect.left
        mov         ecx,WindowRect.bottom
        sub         ecx,WindowRect.top
        invoke      SetWindowPos,hWnd,HWND_NOTOPMOST,WindowRect.left,WindowRect.top,eax,ecx,SWP_SHOWWINDOW
    .else
        mov         m_Windowed,FALSE
        invoke      GetWindowRect,hWnd,addr WindowRect
        invoke      SetWindowLong,hWnd,GWL_EXSTYLE,WS_EX_TOPMOST
        invoke      SetWindowLong,hWnd,GWL_STYLE,WS_POPUP
        invoke      SetWindowLong,hWnd,GWL_WNDPROC,WndProcF_ptr
    .endif

    ret
ToggleFullScreen endp

Creative coders use backward thinking techniques as a strategy.

jj2007

Quote from: caballero on March 24, 2018, 09:55:07 PMI concluded that there's no good way to get it working.

My example posted above works perfectly, and it's just 4 lines. What exactly did not work for you?
jinvoke GetWindowLong, hWnd, GWL_STYLE
xor eax, WS_THICKFRAME
jinvoke SetWindowLong, hWnd, GWL_STYLE, rax
jinvoke SetWindowPos, hWnd, HWND_TOPMOST, eax, eax, eax, eax, SWP_FRAMECHANGED or SWP_NOMOVE or SWP_NOSIZE

avcaballero

Don't know exactly what changes your example. If I use the correct menu option "File / Change border". Attach the window before and after use it.

jj2007

Quote from: caballero on March 25, 2018, 12:11:01 AM
Don't know exactly what changes your example.

There must be something wrong with your Windows version then. On my Win7-64, there clearly is a difference:

jimg

First apologies,  I wrote that last message just before bedtime.  I could have been more tactful.
Also, apologies for the messy code.  It started as a much larger program that I stripped down for an example.

Quote from: jj2007 on March 24, 2018, 07:43:29 PM
Now I went through your code but didn't quite understand what it does. You are creating five windows to the left, then five to the right with identical styles. Afterwards, you try to change the styles of those in the right column. Is that correct?
Not quite correct.  I create the five windows on the left completely with CreateWindowEx, one for each possible type of border available in the dwExStyle parameter.
Then I try to duplicate the same windows the the right of those by first creating the window with the same code except the exstyle is set only to WS_EX_APPWINDOW, with no dwExStyle border set.  Then I used SetWindowLong to change the dwExStyle on that window to one of the five available borders.
The windows on the right should have been identical to those on the left, but they weren't.

I started with the WS_BORDER in the dwStyle parameter because it gave the most visually obvious differences.  Using the other 3 possibilities in dwStyle parameter either worked correctly or resulted in a more subtle difference.

Basically I was hoping I was just forgetting something obvious someone would point out.  At first I thought it was just another thing screwed up about windows 10, but I loaded up windows xp on an old laptop and it did the same thing.


jimg

Here is an example applied to the ascii table program I posted recently.  It's still a work in progress, but here you can see you can select from nine possible borders.

This whole thing came about because I don't like the fat borders one gets in windows 10 high contrast theme.
I use high contrast theme because I dislike the messed up colors on highlighted menus and such in standard themes even more.

It's almost like Microsoft is punishing ungrateful children.  "If you don't like the colors I give you, then here, take this high contrast where you can change the colors but you get fat borders.  Be grateful."  Bah.


avcaballero

I can only notice a different window size in my Windows... don't know. Nevertheless, for a better noticeable example, what I have tried in my example is to make a window with the title bar, the main icon, and the tripplet icons: minimize, maximize, close. And then change this style on demand: to a flat title bar, a title bar with the close button, etc. After a few tries, I left it out.

jimg

Alright, I finally see what's happening.  Even though after several days of searching the internet, I never found it documented.

WS_EX_CLIENTEDGE is added for every case by CreateWindowEx, but not by SetWindowLong

additionally:

for WS_EX_DLGMODALFRAME (double)
      both CreateWindowEx and SetWindowLong also add WS_EX_WINDOWEDGE (raised)

however when you ask for WS_EX_WINDOWEDGE (raised)
   it is ignored (deleted) by both CreateWindowEx and SetWindowLong

Strange.

Note:  This is only for dwStyle=WS_BORDER.   For other values of dwStyle, you get other unexpected combinations.