News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Win32 My First Window

Started by tda0626, April 24, 2024, 11:05:19 AM

Previous topic - Next topic

jj2007

Quote from: NoCforMe on May 07, 2024, 08:05:11 AMCan simplify it a bit:
mov eax, NUMLINES-1
.if iVscrollPos < eax
mov eax, iVscrollPos
; .else ;Not needed
; mov eax, NUMLINES - 1
.endif

tda0626

Fixed the thumb wrap around by checking to see if eax==0. Now it stops at the top.
My page up/down do not work. Clicking the page up/down causes the thumb to go to the bottom of the scrollbar. Can't figure out what is happening.



        CASE            WM_CREATE
                        mov eax, tm.tmHeight
            mov edx, tm.tmExternalLeading
            add eax, edx                        ; tm.tmHeight + tm.tmExternalLeading
            mov cyChar, eax                                 

        CASE    WM_SIZE
           
            mov eax, lParam
            and eax, 0FFFF0000h        ; HIWORD lParam
            mov cyClient, eax
            ret



CASE SB_PAGEUP
                   
                    xor edx, edx
                    mov eax, cyClient
                    div cyChar
                    sub  eax, iVscrollPos
                    mov iVscrollPos, eax
                   
                   
                CASE SB_PAGEDOWN
                   
                    xor edx, edx
                    mov eax, cyClient
                    div cyChar
                    add eax, iVscrollPos
                    mov iVscrollPos, eax

Added Petzold's code for reference...

case SB_PAGEUP:
 iVscrollPos −= cyClient / cyChar ;
 break ;
 case SB_PAGEDOWN:
 iVscrollPos += cyClient / cyChar ;
 break ;

NoCforMe

I think you have your subtract backwards in the SB_PAGEUP case:
C:
 iVscrollPos -= cyClient / cyChar ;

asm:
MOV EAX, cyClient
XOR EDX, EDX
DIV cyChar
SUB iVscrollPos, EAX
Assembly language programming should be fun. That's why I do it.

tda0626

So I got the scrollbar pageup, pagedown, thumbposition, linedown, and lineup to work or it appears like they are working but the window client area does nothing when doing something with the scrollbar. Could someone look at my code and help me out? Been at this for hours now...

My source is attached with the inc file.


TimoVJL

In SysMets2.c
        iVscrollPos = max(0, min(iVscrollPos, NUMLINES - 1));

        if (iVscrollPos != GetScrollPos(hwnd, SB_VERT))
        {
            SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE);
            InvalidateRect(hwnd, NULL, TRUE);
        }
        return 0;
this part of code have to process, as break lead to it in WM_VSCROLL handling.
In debugger put breakpoint to it, just to see why InvalidateRect isn't called.

Also check, printing loop, that it starts with right value.
is this handled ?y = cyChar * (i - iVscrollPos);
May the source be with you

tda0626

Quote from: TimoVJL on May 10, 2024, 05:13:35 PMAlso check, printing loop, that it starts with right value.
is this handled ?y = cyChar * (i - iVscrollPos);

Ahh, that little bit of code was overlooked. I will have to change it when I get home to see if that was the problem. Thank you for the help! It is much appreciated!


Tim

tda0626

Yea that was it. I made that change and it worked but it was scrolling only the szLabel portion. After reviewing my code, I had this bit in there before the other two calls to TextOut.

                        mov eax, cyChar
mul i
mov y, eax

Don't know why I had that in there but I took both instances of it out and now it scrolls all the text at the same time. Awesome! Thanks again for your help!  :biggrin:

NoCforMe

Congrats on your progress.

I just have a general comment about your programming efforts. Looking at some of your comments in your code, it seems to me that you don't really understand what's going on in certain parts of it.

Example: you have this in your WM_CREATE handler where you're calculating text character dimensions:
xor eax, eax
mov al, tm.tmPitchAndFamily ; move tm.tmPitchAndFamily in al because tm.tmPitchAndFamily is a byte value
and eax, 1 ; tm.tmPitchAndFamily & 1

;--------------------------------------------------------------------------------------------------------
; Conditional tm.tmPitchAndFamily & 1 ? 3 : 2 = Checks if value if not zero then use 3 or zero then use 2
;--------------------------------------------------------------------------------------------------------

.if eax == 0 ; if zero then use 2 but since it is a divide by 2
; and then multiply by 2 it is like multiplying cxChar by 1

;--------------------------------------------------------------------------------------
; Step 1: move value of cxChar into eax.
; Step 2: Divide eax by 2.
; Step 3: add eax and cxChar to multiply by 3.
; Step 4: Check if the number is odd by checking to see if bit zero is turned on. If odd, then subtract 1.
; Step 5: move result into cxCaps
;---------------------------------------------------------------------------------------

(First of all I had to do massive reformatting on your text because it's spread out so wide. You must have a huuuuge monitor or something! Makes it very hard for other people to read your code.)

But it's clear from that snippet that you don't get what Petzold is doing there. It has nothing to do with odd or even. What he's doing here is calculating the average width of uppercase characters. He even describes it pretty clearly:
QuoteSYSMETS1 also saves an average width of uppercase letters in the static variable cxCaps. For a fixed-pitch font, cxCaps would equal cxChar. for a variable-width font, cxCaps is set to 150 percent of cxChar. The low bit of the tmPitchAndFamily field in the TEXTMETRIC structure is 1 for a variable-width font and 0 for a fixed-pitch font. SYSMETS1 uses this bit to calculate cxCaps from cxChar:

cxCaps = (tm.tmPitchAndFamily & 1 ? 3: 2) * cxChar / 2;

So that's what the 1 and the 2 and the 3 are for, coming up with either 100% or 150% of cxChar.

Now maybe I'm wrong about this and you do understand what's going on here, in which case I apologize.

I point this out not to ding you for being a bad programmer but to help you become a better one. Again, you really need to understand what's going on in any piece of code before you borrow it or translate it from C to assembly language. Otherwise you're just kind of floundering around in the dark. If you really don't get something after scratching your head, you can always ask here.

Couple other little things; instead of
mov eax, lParam
and eax, 0ffff0000h
shr eax, 010h
mov cyClient, eax
there's a very useful X86 instruction called MOVZX (or MOVSX to preserve the sign of the operand) custom-made for this which puts a byte or a word into a doubleword register in one fell swoop:
movzx eax, WORD PTR lParam
mov cyClient, EAX

I notice you tend to use this sequence a lot to set variables:
push 0
pop wndclass.cbWndExtra
While that's perfectly legal and OK, why not just do this?
mov wndclass.cbWndExtra, 0

Assembly language programming should be fun. That's why I do it.

NoCforMe

Sorry, my bad: that code should be
movzx eax, WORD PTR lParam + 2
mov cyClient, EAX
since you're after the high word of lParam here.
Assembly language programming should be fun. That's why I do it.

tda0626

I do understand most of the code but there are portions of it that I will have revisit and analyze. I will keep at it though and eventually it will come to me.

I did some reading on what LOWORD and HIWORD were and were going by how they were defined but it is nice to know a shortcut like movzx. That would have made my life a little easier but it was nice to use the some bitwise operations just for the practice. My memory is fuzzy but I remember doing bitwise or on ASCII letters to make them lower or upper case and some simple xor encryption back in the day along with some other stuff.

Don't have a massive monitor, just a 27".

I am working on sysmets3 now but when I assemble it, it doesn't recognize the SCROLLINFO struct members. I got a crap ton of undefined symbol errors for nPos, cbSize, ect.. I checked the windows.inc and it is defined in there with those members but masm for some reason doesn't make the connection. Anyone know why?

Defined it in my window procedure like this just like a did with the Paint struct and Text Metric struct.
local si:SCROLLINFO

NoCforMe

Can't use si; that's the name of a register (16-bit lower half of ESI).
Try a different name.

To make a character (in AL) uppercase:
    AND   AL, 5FH
To make it lowercase:
    OR    AL, 20H
(Interesting; 20H is the space character)
Assembly language programming should be fun. That's why I do it.

tda0626

Quote from: NoCforMe on May 11, 2024, 10:56:37 AMCan't use si; that's the name of a register (16-bit lower half of ESI).
Try a different name.


Ok now I feel stupid. lol Can't believe I didn't see that.

NoCforMe

Quote from: tda0626 on May 11, 2024, 11:23:45 AM
Quote from: NoCforMe on May 11, 2024, 10:56:37 AMCan't use si; that's the name of a register (16-bit lower half of ESI).
Try a different name.

Ok now I feel stupid. lol Can't believe I didn't see that.

Be kind to yourself.
You're at the stage where you're learning by making mistakes. (Just try not to make the same mistake more than 2 or 3 times!)

That's actually the best way to learn.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Just a note about names:
You translated Petzold's SYSMETS3 program thinking you could use the same names he did. Now in C, si is nothing special, but in MASM it's a reserved word (a register name).

Likewise, there are other "gotchas" to be aware of. For instance, if you ever play around with treeview controls, you'll be using a structure called TVITEM:
typedef struct tagTVITEM {
  UINT      mask;
  HTREEITEM hItem;
  UINT      state;
  UINT      stateMask;
  LPSTR    pszText;
  int      cchTextMax;
  int      iImage;
  int      iSelectedImage;
  int      cChildren;
  LPARAM    lParam;
} TVITEM, *LPTVITEM;

Problem is, "mask" is also a reserved word in MASM, so in the windows.inc file this member has been renamed to _mask:
TVITEMA STRUCT
  _mask            DWORD  ?
  hItem            DWORD  ?
  state            DWORD  ?
  stateMask        DWORD  ?
  pszText          DWORD  ?
  cchTextMax        DWORD  ?
  iImage            DWORD  ?
  iSelectedImage    DWORD  ?
  cChildren        DWORD  ?
  lParam            DWORD  ?
TVITEMA ENDS
Other than this, almost all the names in windows.inc are identical to the Microsoft-defined names, but now and then they aren't, so if you get errors, you might want to take a peek at the include file and see what's what.

And a note about that name, TVITEMA: the "A" is for ANSI, since this is the ANSI version of that structure. The Unicode version is called TVITEMW ("W" for "wide").
Rather than use these names, I just use the generic version of the structure which is TVITEM and let the assembler select the correct actual version (either "A" or "W"; all my code uses ANSI, so I never deal with the Unicode stuff.)
Assembly language programming should be fun. That's why I do it.

tda0626

Thanks, I will keep an eye out for things like that.

I came across this site that writes code to what you specify in x86 assembly and had it create a program like sysmets3. It was interesting to see the AI's take on how it handles printing the info to the screen and adding the scrollbars. There were a crap ton of errors when assembling the code but I finally did get it to assemble and link but it doesn't work.  :biggrin: One thing I liked, is how the AI split the HORZ and VERT scrolling handling in separate functions. I will see if I can get it to work since it is easier to follow. 


Tim