I'm trying to center a bitmap in the middle of the client area as far as the width of the client area goes using the following code. I think it should work but what is happening is its showing up too far to the left. Tell me i'm not insane or tell me there is something wrong with it.


mov eax,rect.right < The width of the client area
sub eax,BMW < The width of my bitmap
xor edx,edx
mov ebx,2
div ebx
mov Xstartposition, eax < X position for bitblt


Thanx
Posted on 2001-09-24 19:54:20 by titan
Your not crazy...

But i think i see *where* the problem exists. (based on what you have told us).

Your going on one assumption here (not said, but implied): rect.right == Screen Width. There is no guarentee that this is true. Its is possible for rect.left to have a non-zero value.

From your assumption: Rect.left = 0 and let Rect.right = 100
and BMW = 20.

Then ( 100 - 20 )/2 = 40. If the Client Rect STARTS at 0, then your bimap is centered.

But what if Rect.left = 10. The the calculation above, assuming it was 0, will show your bit map shifted to the left by 10 pixels (as the actual client area starts at 10, not 0).

Hope this helps you see the picture a bit better.. (i may not be right at all either, but it *adds* up to me :) )

BTW: Quick lesson in binary mathematics...

All ingerers are represented by BINARY (base 2) values.

24 dec. == 18 hex == 0001 1000 binary.

Thus 24 = 2^4 + 2^3.

Now, say we want to divid this by a number that is a power of two. Ie) no 2^0 values . In your case 2 = 2^1 so this is valid.

24 / 2 = 12 dec.

It also is:

(2^4 + 2^3)/ 2^1 == 2^(-1) [ 2^4 + 2^3 ]

muliply in the 2^(-1) and we get:

24/2 == 2^3 + 2^2 == 0000 1100 bin.

So, dividing 24 ( 0001 1000 ) by 2 (0000 0010) actualy SHIFTS RIGHT by the exponential of the base 2 divisor (2 = 2^1)!! Thus the result is shifted 1 bit to the right.

This applies to all pure base 2 divisiors. Pure being nothing like 10 dec = 1010 bin, as this is 2^3 + 2^1 and to you can not cleanly invert a denominator which has a sum.

(2^3 + 2^1)^(-1) DOESNT EQUAL (2^(-3) + 2^(-1))!!!

So you can NOT divide by 10 with shifting. Only pure values:
2,4,8,16,32,64,128,256,512,1024,4096, 8192,16384, 32768 etc. etc.


[[ Interesting note, You CAN however MULTIPLY a number my a non-pure base 2 number such as 10!! This is because you do not need to invert the non-pure number, its already in the numerator... ]]

24 * 10 == (2^4 + 2^3) * (2^3 + 2^1)

== 2^3*(2^4 + 2^3) + 2^1*(2^4 + 2^3)

== 24 SHIFT LEFT 3, PLUS, 24 SHIFT LEFT 1

== 1100 0000 + 0011 0000 == 1111 0000 == 0F0 Hex == 240 Dec.

This makes sense, as 8 bits = 256, and 24*10 is 240. So the difference is 16 between them, which is the 4 least significant zero bits in the answer.

These things are handy to know if your multipling or dividing by constants. You can take the time and figure out how may shifts needed to do the same thing as MUL or DIV. But this obviously is not to your advantage if you dont know the divisor or multiplier before run time. In this case your only option is to use the MUL and DIV commands (or other math ops..)


------------------------------------------------------------------
Anyways, back to your code:

Your code could be cleaned up and be much more efficient by:
mov eax,rect.right < The width of the client area


sub eax, rect.left ; <<<< MY HUNCH WHERE YOU BUG IS

sub eax,BMW < The width of my bitmap

shr eax, 1 ; <<<<<< DIVIDE BY 2

add eax, rect.left ; Now centered between Rect.left and Rect.right

mov Xstartposition, eax < X position for bitblt



Hope this helps...

NaN
Posted on 2001-09-24 23:58:35 by NaN
Nan that was certainly copied and pasted.

Your very informative in your replies.

Maybe you should be a teacher.

Hell...you are a teacher.

I'll let you know if your solution involving rect.left helps

Thanx:alright:
Posted on 2001-09-25 00:05:55 by titan
I dont try to be... but your correct to some degree.. :) I spent the last year as a TA in university.. And i really enjoyed the experience...

Too bad a teachers pay is nowhere comparable to a microwave engineer's :grin: .

(( PS: if you did cut and paste, do it again, as i *just* fixed a bug in one off the eqn's ))

NaN
Posted on 2001-09-25 00:09:36 by NaN
done
pasted everything

whether your solution works or not don't matter
the info in the replies is significant

thanx again
Posted on 2001-09-25 00:24:53 by titan
NaN:

The soltuion became specifying the window handle as a parameter to be sent to the thread for use in the GetClientRect function. Initially this function was being called before the call to ThreadProc. This makes clear to me your assertion that one must not assume rect.left and rect.right will necessarily contain proper client area values in different threads even if the RECT structure has already been initialized. However your method to correct the "BUG" had no effect on the bitmap position. This prompted me to think that you too made an assumption. I believe your asumption was this. (Correct me if i'm wrong)

Assumption: With a client width of 1024
If rect.right == 1044
Then rect.left == 20

In other words the "Range" is always static.

If the range were static....your method should have worked.

Just blowing hot air here.

Thanx

____________________________________

ThreadProc PROC USES ebx hhwnd:DWORD

__________________________________

invoke GetClientRect, hhwnd,addr rect

mov eax,rect.right
sub eax,BMW
shr eax,1
mov SXPOS,eax

:alright:
Posted on 2001-09-25 12:04:35 by titan
Sorry, I wasn't assuming any size.. I was however assuming the RECT was properly filled by GetClientRect. That is why i subtract the left val from the right val to get an difference value between them.. It could be 44 or it could be 1024.. i dunno. but this was the *safest* starting point to then calculate the mid point for your bitmap... :)

Glad you got it working tho...

NaN
Posted on 2001-09-25 23:29:59 by NaN