Hello all!

I have a bit of code which, although it doesn't need "optimization" especially for speed, it is kinda ugly. I was wondering if people had any interesting ways of simplifying a case-like statement.

Specifically, the code I'm talking about is regarding scrolling the document. It compares each case of WM_VSCROLL, adds a value to the current scroll position, and redraws it by calling a proc I've defined called Scroll (imaginative, huh?)

There is a similar batch of code for handling key strokes that have the same effect.

So... any ideas???



WM_VSCROLL_HANDLER:
mov eax,wParam
cmp ax,SB_PAGEUP
jne @F
mov eax,ScrollInfo.nPos
sub eax,PageHeight
invoke Scroll,hWin,eax
ret
@@:
cmp ax,SB_PAGEDOWN
jne @F
mov eax,ScrollInfo.nPos
add eax,PageHeight
invoke Scroll,hWin,eax
ret
@@:
cmp ax,SB_LINEUP
jne @F
mov eax,ScrollInfo.nPos
sub eax,20
invoke Scroll,hWin,eax
ret
@@:
cmp ax,SB_LINEDOWN
jne @F
mov eax,ScrollInfo.nPos
add eax,20
invoke Scroll,hWin,eax
ret
@@:
cmp ax,SB_THUMBPOSITION
jne @F
shr eax,16
mov ScrollInfo.nPos,eax
invoke InvalidateRect,hWin,NULL,TRUE
ret
@@:
cmp ax,SB_THUMBTRACK
jne @F
shr eax,16
mov ScrollInfo.nPos,eax
invoke InvalidateRect,hWin,NULL,TRUE
@@:
ret
Posted on 2002-05-09 15:02:35 by chorus
Posted on 2002-05-09 15:20:00 by bitRAKE
BitRake,
I have seen these threads before. Thanks though. The reason I put the post up regardless of this fact is that I am looking at a very specific case vs. very general. For instance, the case handling of a windows message loop, where virtually every branch is completely different is not what I was looking for (although it does give me ideas). I find that this particular loop I'm looking to optimize is very "symmetric" in that most every branch calls the same function with a different value loaded.

Regards

--Chorus
Posted on 2002-05-09 16:18:22 by chorus
I like macro's for the job. Im not saying this is the 'fastest' or 'smallest' approach, but it is quite readable as a case like structure, and the extra jump's arnt that big of a deal (most cases).

Macro #1: IF_MSG:
IF_MSG MACRO WMsg:REQ, DoJmp:REQ

cmp uMsg, WMsg
jz DoJmp
ENDM


Macro #2: IF_WPARAM:
IF_WPARAM MACRO WPrm:REQ, DoJmp:REQ

cmp wParam, WPrm
jz DoJmp
ENDM


Example framework of their use:
_WndECProc proc USES EBX _hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD


IF_MSG WM_CASE1, Do_Case1
IF_MSG WM_CASE1, Do_Case2
IF_MSG WM_COMMAND, Do_Command

; Default Case:
@return:
invoke DefWindowProc,_hWnd,uMsg,wParam,lParam
ret

@end:
xor eax, eax
jmp @return

;-------------------------------
Do_Case1:
;-------------------------------
; Case Code Here
jmp @end
;-------------------------------
Do_Case2:
;-------------------------------
; Case Code Here
jmp @end
;-------------------------------
Do_Command:
;-------------------------------
IF_WPARAM 1010, Do_Exit
IF_WPARAM 1011, Do_Something

jmp @return
;-=-=-=-=-=--=-=-=-=-=--=
Do_Exit:
;-=-=-=-=-=--=-=-=-=-=--=
invoke SendMessage,hWnd,WM_SYSCOMMAND,SC_CLOSE,NULL
jmp @end
;-=-=-=-=-=--=-=-=-=-=--=
Do_Something:
;-=-=-=-=-=--=-=-=-=-=--=
; Something code here
jmp @end

I like this when pounding out new ideas and quickly handling stuff. Its also flexible, if you wanted one case to bleed into the next simply dont add the "jmp @end". Default cases are at the end of the IF_ Macro's. For both, the default here is 'passing the buck' to the windows' default handler.

Hope it helps
:alright:
NaN
Posted on 2002-05-09 16:51:00 by NaN

I find that this particular loop I'm looking to optimize is very "symmetric" in that most every branch calls the same function with a different value loaded.
Then use a table and don't branch. :) The fastest approach will take much manual manipulation. By the code above, it looks like you'll have one multi-way branch table.
Posted on 2002-05-09 16:54:11 by bitRAKE
Haha! Size-optimizing :) Here's the best I can make of it in 10 minutes.
Please note I'm a TASM coder (but learning MASM), and I don't know much about MASM's addressing syntax yet. More specifically, I'v assumed PageHeight is a variable. This causes the PAGEDOWN and PAGEUP compares to be in a different order than the original. If PageHeight is a constant (with EQU or =), then you can keep the original order by negating it were it is used (as in the LINEUP/LINEDOWN case)

WM_VSCROLL_HANDLER:
mov eax,wParam
mov ebx, PageHeight
cmp ax, SB_PAGEDOWN
je @@Scroll

neg ebx
cmp ax,SB_PAGEUP
je @@Scroll

mov ebx, -20
cmp ax,SB_LINEUP
je @@Scroll

neg ebx
cmp ax,SB_LINEDOWN
je @@Scroll

cmp ax,SB_THUMBPOSITION
je @@Scroll_Page
cmp ax,SB_THUMBTRACK
jne @@No_Scroll
@@Scroll_Page:
shr eax,16
mov ScrollInfo.nPos,eax
invoke InvalidateRect,hWin,NULL,TRUE
ret

@@Scroll:
add ebx,ScrollInfo.nPos
invoke Scroll,hWin,ebx
@@No_Scroll:
ret
Posted on 2002-05-10 11:59:07 by james
Thanks for the replies :)

NaN, I like the ideas of the macros, it is very readable. However, I am actually implementing the version James posted (thanks James). It suits my needs pretty well, especially considering that I can merge my WM_KEYDOWN message with it :)

Thanks again everybody

--Chorus
Posted on 2002-05-10 13:35:12 by chorus