News:

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

Main Menu

Adventures in programming: Treeviews, directory scanning, recursion

Started by NoCforMe, April 05, 2024, 10:36:19 AM

Previous topic - Next topic

zedd151

Quote from: NoCforMe on April 21, 2024, 02:10:56 PMThanks!

I'll be looking for that big fat check in the mail.   :greensml:
Now go fix the other (bigger) problem first. You can narrow this one down later.
:azn:

NoCforMe

My guess is the answer may lie somewhere in this code: this is what happens when the user clicks on a treeview item containing a picture:
; Apparently someone clicked on our treeview: EDX--> NMTREEVIEW structure:
; No can do if we're busy:
CMP BusyFindingFlag, TRUE
JNE @F
INVOKE MessageBeep, MB_ICONASTERISK
JMP zero_exit

@@: LEA EAX, [EDX].NMTREEVIEW.itemNew ;Point to the TVITEM struct. within it.
MOV [EAX].TVITEM._mask, TVIF_PARAM or TVIF_HANDLE
PUSH EAX ;Save ptr.
INVOKE SendMessage, TreeviewHandle, TVM_GETITEM, 0, EAX
POP EDX ;EDX--> TVITEM
MOV EDX, [EDX].TVITEM.lParam ;EDX--> our FILEINFO element.
PUSH EDX
INVOKE SetWindowText, PathDisplayHandle, ADDR [EDX].FILEINFO.pathName
POP EDX

; Is it a folder or a file?
TEST [EDX].FILEINFO.flag, $folder
JNZ zero_exit

; It's a file, so show the picture--must make filename Unicode:
MOV fiOffset, EDX ;Save ptr. for later.
INVOKE MakeUnicodeName, ADDR [EDX].FILEINFO.pathName, ADDR unicodeName

; Load image:
INVOKE GdipLoadImageFromFile, ADDR unicodeName, OFFSET GdiHbitmap

; Get width & height of bitmap:
INVOKE GdipGetImageWidth, GdiHbitmap, OFFSET ImgStruct.imgW
INVOKE GdipGetImageHeight, GdiHbitmap, OFFSET ImgStruct.imgH

; Get width & height of display window:
INVOKE GetClientRect, PicDisplayHandle, ADDR gpRect
MOV EAX, gpRect.right
SUB EAX, gpRect.left
SUB EAX, $imgBorder * 2
MOV ImgStruct.winW, EAX
MOV EAX, gpRect.bottom
SUB EAX, gpRect.top
SUB EAX, $imgBorder * 2
MOV ImgStruct.winH, EAX

; Scale image to our window:
INVOKE ScaleImg2Win, OFFSET ImgStruct

; Show it:
INVOKE InvalidateRect, PicDisplayHandle, NULL, TRUE

; Show pic info below preview:
MOV EDX, fiOffset
LEA EAX, [EDX].FILEINFO.pathName
ADD EAX, [EDX].FILEINFO.rootLoc
INVOKE wsprintf, ADDR buffer, OFFSET PicInfoFmt, EAX, ImgStruct.imgW, ImgStruct.imgH
INVOKE SetWindowText, PicInfoHandle, ADDR buffer
MOV PictureIsUp, TRUE
JMP zero_exit

Something here has a beneficial effect on the progress bar and makes it work thereafter. Somehow. Notice that nowhere does the handle to that control (ProgressBarHandle) appear.
Assembly language programming should be fun. That's why I do it.

zedd151

It's just after midnight here, I gotta go. I'll look into this further, tomorrow. Or should I say later today.
:azn:

zedd151

Using another pristine source code: (from attachment in post #146)


DisplayWindowProc   PROC hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
   LOCAL   hDC:HDC, gdiHgraphics:DWORD, ps:PAINTSTRUCT, gpRect:RECT

   MOV   EAX, uMsg
 ;    CMP   EAX, WM_PAINT  ;;;changed
 ;    JE   do_paint       ;;;changed
   CMP   EAX, $MSG_ClearPicWindow
   JE   do_clear


I commented out the "je do_paint"...
Getting closer to a real solution.
:azn:

zedd151

From a clean unmodified source: (from attachment in post #146)

;==============================
;  WM_PAINT handler
;==============================
do_paint:
 ;    CMP    PictureIsUp, FALSE  ;; <--- commented out
 ;    JE    zero_exit            ;; <--- commented out

marquee is 'marqueeing' now --- when it is supposed to...
You will have to test NoCforMe, how this affects anything else...


:azn:

NoCforMe

Well, OK, you're obviously on the right track: I just tried displaying a picture in that window before the initial disk scan, and it made the progress bar marquee work.

But you know me: I'm not satisfied, because we still don't know why that makes the dang thing work. I could add a "splash screen" which would make it work, but I still wouldn't know what caused the underlying problem.

Apparently there's some kind of interaction between the progress bar control and GDI+. But what?

I don't like that as a "fix", because it ends up going through the WM_PAINT handler even if there's not a valid GDI+ bitmap handle (GdiHbitmap) to display.

Good work on your part, though.
Assembly language programming should be fun. That's why I do it.

zedd151

Seems that the code must flow through the WM_PAINT handler for the marquee to animate. At any rate, I'm done with that for now. Maybe I will look more into it at another time.

You could bypass anything there that would use any handle (test for valid handle) allowing the progress bar to work. Shouldn't be necessary to bypass WM_PAINT altogether....  I might could try a couple things along that line if I have time later tonite.
:azn:

NoCforMe

A Martian programmer reading this thread might scratch his head and say "WTF are these hue-mons obsessing so much over a little itty-bitty rectangle that shows a moving blob?". And they might be right at that.

But look at the lengths that some people will go to in order to get the progress bar they like. Wow.

Heh; maybe I should adapt my own barber-pole control for this program.
Assembly language programming should be fun. That's why I do it.

zedd151

Quote from: NoCforMe on April 22, 2024, 06:36:20 AMA Martian programmer reading this thread might scratch his head and say "WTF are these hue-mons obsessing so much over a little itty-bitty rectangle that shows a moving blob?". And they might be right at that.

But look at the lengths that some people will go to in order to get the progress bar they like. Wow.

Heh; maybe I should adapt my own barber-pole control for this program.

:rofl:  :rofl:
That's what happens with too much time on your hands...   :biggrin:
:azn:

NoCforMe

Further research here at NoC Laboratories, GmbH shows that all that's needed to make the progress bar work in "marquee" mode is to invoke the paint routine of the picture-display window proc, by first disabling the "gate" at the top of the WM_PAINT handler:

;==============================
;  WM_PAINT handler
;==============================
do_paint:
; CMP PictureIsUp, FALSE
; JE zero_exit

INVOKE BeginPaint, hWin, ADDR ps
MOV hDC, EAX

; Get graphics "object" from DC handle:
INVOKE GdipCreateFromHDC, hDC, ADDR gdiHgraphics

; Display image at (X,Y) with dimensions (W,H):
; Many thanks to "mabdelouahab" from the MASM32 forum for this.
INVOKE GdipDrawImageRectI, gdiHgraphics, GdiHbitmap,
ImgStruct.imgX, ImgStruct.imgY, ImgStruct.imgWscaled, ImgStruct.imgHscaled
INVOKE EndPaint, hWin, ADDR ps
JMP zero_exit

and then by forcing a repaint, even though there's no valid bitmap to show:

INVOKE InvalidateRect, PicDisplayHandle, NULL, FALSE

What bothers me is that I still don't know why this works ...
Assembly language programming should be fun. That's why I do it.

zedd151

Quote from: NoCforMe on April 22, 2024, 08:18:38 AMWhat bothers me is that I still don't know why this works ...
Is GDI+ taking over all of the graphics functions, I.e. Painting, redrawing, etc...  Must be something with GDI+ I think.

Don't spend too much time on this though, those martians are watching.  :tongue:
:azn:

NoCforMe

The progress bar marquee animation also works if I just clip out all of the GDI+ stuff from the program. So I think I've proven that the problem is definitely an interaction of the progress bar control with GDI+.

I find nothing at all about this on the intertubes, btw.
Assembly language programming should be fun. That's why I do it.

zedd151

If nothing else, at least you narrowed the problem down.
What about using createwindowex for the progress bar, and give it its own wndproc??
Or even run the progress bar in its own thread?

Type correction fubarring my post (iPad post) ...  but you should get the idea.
:azn:

NoCforMe

Quote from: sinsi on April 21, 2024, 05:08:42 AMOK, tracked down the crash
    INVOKE    strcpy, ADDR [EDX].FILEINFO.pathName, ADDR [EBX].FILEINFO.pathName
    INVOKE    _strcat, OFFSET BackslashStr, ADDR [EBX].FILEINFO.pathName
    INVOKE    _strcat, OFFSET FD.cFileName, ADDR [EBX].FILEINFO.pathName
;*** added ***
lea eax,[EBX].FILEINFO.pathName
call strlen
cmp eax,MAX_PATH
jbe @f
 int 3
@@:
;*************
Run in the debugger, stops at the breakpoint with EAX=0115 (277, well over MAX_PATH)
This overwrites some pretty important data in your structure  :biggrin:

The version attached here (.exe only) will log any overlength pathnames and prevent them from being processed. sinsi, could you run this against the path that caused the crash? The program will create a log file (PicView.log) in the folder containing the .exe, and it should contain any overlength pathnames.
Assembly language programming should be fun. That's why I do it.

sinsi

Interesting...running the program from home, the log is empty and everything works
 - the dialog combo doesn't close when I first click on it, and shows a list
 - the marquee works from the start

I can't check the work PC until tomorrow night (that's where the problems are).

Weird.