IRC Log: Windows_GUI_Glass_Buttons

[2009-03-27 05:18]Napalm:Is anyone still around?
[2009-03-27 05:19]Napalm:lol
[2009-03-27 05:19]Enigma:yeah I'm here
[2009-03-27 05:19]anubis:lol
[2009-03-27 05:19]Echo:yes
[2009-03-27 05:19]anubis:barely
[2009-03-27 05:19]unfunf:Yes
[2009-03-27 05:19]Napalm:should we wait for others? or do we think this is everyone?
[2009-03-27 05:19]Philkill:im also here
[2009-03-27 05:19]Echo:its because its late right now i assume
[2009-03-27 05:19]anubis:you mean like wait til tomorrow lol
[2009-03-27 05:20]Echo:you could do it tomorrow
[2009-03-27 05:20]Echo:this code deserves it
[2009-03-27 05:20]unfunf:no
[2009-03-27 05:20]unfunf:bah
[2009-03-27 05:20]Napalm:haha
[2009-03-27 05:20]unfunf:there will be logs
[2009-03-27 05:20]anubis:ya i agree with echo
[2009-03-27 05:20]Napalm:unfunf: its your call, i dont care.. the code is done now
[2009-03-27 05:20]Echo:unfunf: this method of doing it is sick
[2009-03-27 05:20]unfunf:mother fucker
[2009-03-27 05:20]unfunf:okay
[2009-03-27 05:20]Echo:i think more people should be here to enjoy it
[2009-03-27 05:20]Napalm:sick == code
[2009-03-27 05:20]Napalm:sick == good
[2009-03-27 05:20]Enigma:what is da time napalm?
[2009-03-27 05:20]Napalm::|
[2009-03-27 05:20]Echo:yup
[2009-03-27 05:20]Echo:sick = good
[2009-03-28 00:06]Napalm:ok people
[2009-03-28 00:06]Napalm:who do we have here
[2009-03-28 00:06]Napalm:come on, we are going to make this an interactive lecture :)
[2009-03-28 00:06]Uranium-239:"/names"
[2009-03-28 00:06]eth0:woot!
[2009-03-28 00:07]Unknown:yo
[2009-03-28 00:07]wubbster::D
[2009-03-28 00:07]src::O
[2009-03-28 00:07]Napalm:hey Bob_Plonker
[2009-03-28 00:07]Xorvats::P
[2009-03-28 00:07]Bob_Plonker:Howdy bud
[2009-03-28 00:07]Echo:im here of course
[2009-03-28 00:07]Echo::)
[2009-03-28 00:07]Uranium-239:Naltax isn't
[2009-03-28 00:07]eth0:lol
[2009-03-28 00:07]Echo:good
[2009-03-28 00:07]Napalm:ok
[2009-03-28 00:07]tktech:ACTION Readies his X Cannon to take on the GDI MG's
[2009-03-28 00:07]Napalm:now here is the source we will be discussing
[2009-03-28 00:07]Napalm:http://www.netcore2k.net/downloads/glassbuttons_src.zip
[2009-03-28 00:08]Napalm:help yourselfs
[2009-03-28 00:08]Napalm:MSVC6 project, Executable included
[2009-03-28 00:08]Napalm:resize click and play with it
[2009-03-28 00:08]Napalm:while i am doing the talk you can all read the comments and i will be taking questions at the end
[2009-03-28 00:08]Uranium-239:sweet
[2009-03-28 00:09]eth0:ACTION goes ooooo ahhhhhh
[2009-03-28 00:09]Napalm:shit
[2009-03-28 00:09]Napalm:one momenyt
[2009-03-28 00:09]Napalm:looks like im missing a file
[2009-03-28 00:10]Bob_Plonker:lol
[2009-03-28 00:10]Napalm:ok zip is updated
[2009-03-28 00:10]Napalm:redownload
[2009-03-28 00:11]Xorvats:look nice
[2009-03-28 00:11]Unknown:aye
[2009-03-28 00:11]Napalm:for those of you on linux at the moment here is a screen-shot http://www.netcore2k.net/GlassButtons.jpg
[2009-03-28 00:11]Napalm:its slightly older than the final
[2009-03-28 00:11]Napalm:Ok. on with the talk
[2009-03-28 00:12]eth0:the type*
[2009-03-28 00:12]Napalm:i will first cover some of the basics, but as i said before this is really for the intermediate windows programmer
[2009-03-28 00:12]Napalm:i will first cover some of the basics, but as i said before this is really for the intermediate windows programmer
[2009-03-28 00:12]Napalm:to create GUI apps in windows we call a subset of the windows api
[2009-03-28 00:13]Napalm:the two main librarys we deal with are kernel32 and user32
[2009-03-28 00:13]Napalm:these form the user-mode side of the win32 subsystem
[2009-03-28 00:15]Napalm:we receive GUI notifications of user input and response via a messaging system
[2009-03-28 00:15]Napalm:if you look in GlassButtons.cpp I will describe the control flow as the programs load
[2009-03-28 00:16]Napalm:*program
[2009-03-28 00:16]Napalm:i assume you all have had time to take a quick glance over the other files in the project
[2009-03-28 00:16]Bob_Plonker:quick, yup
[2009-03-28 00:17]Napalm:Once windows starts our program and initalizes our process it gives our application control
[2009-03-28 00:17]Napalm:the function which windows calls is WinMain
[2009-03-28 00:18]Napalm:here we startup and initalise everything we need for our program to execute correctly
[2009-03-28 00:18]Napalm:as you can see in the source we start the GDI+ library and create a new class instance for our window
[2009-03-28 00:19]Napalm:for those of you that are not all to familar with C++ the TestWindow class is derived from BaseWindow
[2009-03-28 00:19]Napalm:this means all of the members that is to say methods and variables of BaseWindow become part of TestWindow
[2009-03-28 00:20]Napalm:they are not copied to the new class but mapped
[2009-03-28 00:20]Napalm:i wont go into detail about this but you can find info here: http://en.wikipedia.org/wiki/Virtual_table
[2009-03-28 00:21]Napalm:now
[2009-03-28 00:21]Napalm:since our GlassButton class and TestWindow class share some common factors, they are both Windows
[2009-03-28 00:22]Napalm:both have to have a Window Handle Value (unique id) to communicate our intentions to the win32 api
[2009-03-28 00:22]Napalm:you will find this stored as HWND m_hWnd; in BaseWindow
[2009-03-28 00:22]Napalm:As i said before we recieve messages from widows
[2009-03-28 00:22]Napalm:windows
[2009-03-28 00:23]Napalm:but hows does windows know what to tell us about
[2009-03-28 00:23]Napalm:well everything in the windows GUI system is a 'window'
[2009-03-28 00:23]Napalm:that means a Button/Scrollbar/Menu/Custom-Control/Anything are all 'windows'
[2009-03-28 00:24]Napalm:these are seperated by what we call a Class
[2009-03-28 00:24]Napalm:we define a class structure and register it with windows so that when we decide to create a window it knows what base properties to give it
[2009-03-28 00:25]Napalm:in this class structure we also tell windows what function we want to recieve messages on
[2009-03-28 00:25]Napalm:this is of type WNDPROC
[2009-03-28 00:25]Napalm:now
[2009-03-28 00:27]Napalm:the idea behind using the C++ classes is so that we can dispatch messages and managed window state
[2009-03-28 00:27]Napalm:you will see in WinMain we attempt to create an instance of TestWindow
[2009-03-28 00:28]Napalm:and after that we can use the HWND cast operator to perform actions on our window by simply directing it to the class
[2009-03-28 00:28]Napalm:to start with we animate the window to show it on the screen
[2009-03-28 00:29]Napalm:http://www.netcore2k.net/downloads/glassbuttons_src.zip
[2009-03-28 00:30]Napalm:after that in WinMain we use the GetMessage and friends to hand our the messages we receive from windows to our functions
[2009-03-28 00:31]Napalm:by default the windows api tells us that any message we dont want to handle should ideally be passed on to DefWindowProc so it can choose to do the default action
[2009-03-28 00:32]Napalm:this is so that when a user uses things like hot keys to minimize the window, it will actually work. if you did not pass the WM_SYSCOMMAND message on to the default handler then you would need to provide the code to action these events
[2009-03-28 00:33]Napalm:ok, so now lets take a look at BaseWindow.h
[2009-03-28 00:33]Napalm:here we define the class and give it some protected variables
[2009-03-28 00:33]Napalm:if the C++ newbs are out there here is a quick definition of the class qualifiers
[2009-03-28 00:34]Napalm:protected: private to this class and derived classes
[2009-03-28 00:34]Napalm:private: private to this class and can only be used by its members
[2009-03-28 00:34]Napalm:public: is accessable from outside the class with global access
[2009-03-28 00:34]Napalm:these are the only access schemes we have, so we need to really use them to great effect
[2009-03-28 00:35]Napalm:for instance we dont want to give public write access to the m_hWnd variable since its managed by BaseWindow
[2009-03-28 00:36]Napalm:we wouldnt want an another piece of code to accidentally change its value and mess up message handling in our program
[2009-03-28 00:36]Napalm:another value we are always going to use is the client-rect
[2009-03-28 00:36]Napalm:i suppose i better explain what this is
[2009-03-28 00:36]Uranium-239:could another piece of code modify it by writing to its memory address?
[2009-03-28 00:36]Uranium-239:or would that raise an exception
[2009-03-28 00:37]Napalm:it would be very difficult to access it
[2009-03-28 00:37]Napalm:since its a member variable is dynamic in nature so is the address
[2009-03-28 00:37]Uranium-239:ok
[2009-03-28 00:38]Napalm:it would not raise an exception, but it would be hard to access
[2009-03-28 00:38]Napalm:back to the talk
[2009-03-28 00:38]Napalm:ok, client-rect
[2009-03-28 00:38]Napalm:each window/button/control
[2009-03-28 00:38]Napalm:whatever
[2009-03-28 00:38]Napalm:has two main areas it defines
[2009-03-28 00:39]Napalm:'non-client area' and 'client area' the two restrictions are that they can only be rectangles and the 'client area' must fit inside the 'non-client area'
[2009-03-28 00:39]Napalm:rohitab: http://www.netcore2k.net/downloads/glassbuttons_src.zip
[2009-03-28 00:40]rohitab:thanks
[2009-03-28 00:40]Napalm:the non-client area is where a overlapped (standard windows) has its window caption bar with the minimize/max/close buttons
[2009-03-28 00:41]Napalm:the non-client area also encompasses the window frame aka border
[2009-03-28 00:41]Napalm:now everything you see on y
[2009-03-28 00:41]Napalm:your windows machine is actually drawn/painted
[2009-03-28 00:41]Napalm:there is no real level of control
[2009-03-28 00:41]Napalm:all windows handle mouse and keyboard input and react accordingly
[2009-03-28 00:42]Napalm:so the standard windows push button simply 'feels' like a button because it looks and acts like one
[2009-03-28 00:42]Napalm:its really the same as any other window
[2009-03-28 00:42]Napalm:now even child-windows (controls on windows) can have a non-client area
[2009-03-28 00:43]Napalm:for instance the standard edit-box (text entry field) has a non-client area where it draws the window edge
[2009-03-28 00:43]Napalm:the old-classic windows look used two styles
[2009-03-28 00:43]Napalm:WS_BORDER and WS_EX_CLIENTEDGE
[2009-03-28 00:44]Napalm:the client-edge gives the window the sunken look
[2009-03-28 00:44]Napalm:the border style gives it a single pixel black border
[2009-03-28 00:44]Napalm:ok, so we have established some basic facts
[2009-03-28 00:44]Napalm:we have a non-client area and client-area
[2009-03-28 00:45]Napalm:now, we recieve a WM_PAINT and WM_ERASEBKGND messages to draw the content in windows
[2009-03-28 00:45]Napalm:windows uses a two stage system, mainly as a fall back from the days of old and windows was 3.1
[2009-03-28 00:46]Napalm:simply because you wouldnt ever do any drawing operations you could avoid back then because the system was task-swapping and not pre-empting
[2009-03-28 00:46]Napalm:so the longer you took drawing the less time other applications got to do their thing
[2009-03-28 00:47]Napalm:the erase background uses our windows-class's background brush to fill the window
[2009-03-28 00:47]Napalm:by default (DefWindowProc)
[2009-03-28 00:48]Napalm:the flashing/flickering you see for instance when you resize an instance of notepad.exe is because it recieves a WM_ERASEBKGND message which paints the entire client-area white and then it draws the text back in WM_PAINT
[2009-03-28 00:49]Napalm:would could intercept the WM_ERASEBKGND message and stop it being passed to DefWindowProc this would stop that flickering
[2009-03-28 00:49]Napalm:but this also means we now have to paint the entire window in WM_PAINT
[2009-03-28 00:49]Napalm:or we would simple get "copies" of the text repeating on o
[2009-03-28 00:49]Napalm:us
[2009-03-28 00:50]Napalm:this still has an issue
[2009-03-28 00:50]Napalm:if we were to paint our window white and then draw text on it the time in-between these two things would show a flicker
[2009-03-28 00:52]eth0:woops
[2009-03-28 00:52]Napalm:this is because we actually draw to the bitmap memory of the screen
[2009-03-28 00:53]Napalm:and the screen refreshes very quickly at say 70Hz (thats 70 times a second)
[2009-03-28 00:53]Napalm:this is why we see a flicker
[2009-03-28 00:54]Napalm:since the screen refreshes inbetween us painting to the background and then painting say text on top
[2009-03-28 00:55]Napalm:so, to fix this we are going to need to paint our window to a memory bitmap and then copy that bitmap in one foul swoop to the screen
[2009-03-28 00:55]Napalm:this as a disadvantage in the fact that is memory expensive
[2009-03-28 00:56]X-N2O:Back-buffer HDC?
[2009-03-28 00:56]Uranium-239:im guessing a double buffer
[2009-03-28 00:56]Napalm:say a 1024x768x24bit is 2.3MB just for the bitmap data
[2009-03-28 00:56]Uranium-239:and copy it over on WM_PAINT messages
[2009-03-28 00:56]Napalm:shhh
[2009-03-28 00:57]Napalm:si
[2009-03-28 00:57]Napalm:so
[2009-03-28 00:57]Napalm:it solves it and with todays memory and speeds its not a real issue
[2009-03-28 00:57]Napalm:since the memory bitmap is only uses for a split second during the painting its not too expensive
[2009-03-28 00:57]Napalm:but to allocate and then free that every time is
[2009-03-28 00:58]Napalm:so, what we want to do is to create a static bitmap outside of the message handling so we can resuse the same bitmap
[2009-03-28 00:58]Napalm:this solves flickering
[2009-03-28 00:58]eth0:hold on
[2009-03-28 00:58]Napalm:and the term is also called double-buffering
[2009-03-28 00:59]eth0:so just to be clear, copying it from memory paints it at a faster screen rate then ... ?
[2009-03-28 00:59]Uranium-239:nope
[2009-03-28 00:59]Uranium-239:its about copying it over in one swoop
[2009-03-28 00:59]Napalm:ltos of editing operations on the bitmap are going to be slower than one single block copy
[2009-03-28 00:59]Napalm:*lots
[2009-03-28 00:59]eth0:ahh ok thank you
[2009-03-28 01:00]Napalm:now
[2009-03-28 01:00]Napalm:its always better to try and not over-paint pixels
[2009-03-28 01:00]Napalm:this as i said is what causes the flicker
[2009-03-28 01:00]Napalm:so instead of a memory bitmap we could always try to avoid paint over previously painted pixels
[2009-03-28 01:01]Napalm:this is quite impossible with say text
[2009-03-28 01:01]Napalm:but if you wanted to display a grid, white background with grey lines
[2009-03-28 01:01]Napalm:the grey lines would flash everytime the white background is painted
[2009-03-28 01:02]Napalm:but if we were to say draw lots of small white rectangles a pixel apart and then fill the gaps with grey lines
[2009-03-28 01:02]Napalm:there would be no flicker
[2009-03-28 01:02]Napalm:so, think about what your going to paint before you paint it
[2009-03-28 01:02]Napalm:it helps
[2009-03-28 01:02]Napalm:so, we've kinda delved in to the land of GDI
[2009-03-28 01:03]Napalm:Graphics Device Interface
[2009-03-28 01:03]Napalm:needed to look that one up, long time
[2009-03-28 01:03]Napalm:so
[2009-03-28 01:04]Napalm:GDI is like a sub-section of win32
[2009-03-28 01:04]Napalm:it serves as a system for drawing
[2009-03-28 01:05]Napalm:now as for windows have HWND (Handle Window) on GDI we also have HDC
[2009-03-28 01:05]Napalm:Handle to Device Context
[2009-03-28 01:05]Napalm:now a HDC is a representation of a group of objects
[2009-03-28 01:05]Napalm:these objects are what the windows GDI functions use to draw with
[2009-03-28 01:06]Napalm:for instance lets say we want to draw a rectangle
[2009-03-28 01:06]Napalm:we would use the following API
[2009-03-28 01:06]Napalm:BOOL Rectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
[2009-03-28 01:07]Napalm:now as you can see, how come we cant specify a color for our rectange?
[2009-03-28 01:07]Napalm:how about if we want to fill our rectangle?
[2009-03-28 01:07]Napalm:well this is because the Rectangle API will do it for us
[2009-03-28 01:07]Napalm:it uses the currently "selected" objects in the HDC
[2009-03-28 01:08]Napalm:so lets say we want to draw a 10x10 pixel rectangle with a 2 pixel red border with a yellow inside
[2009-03-28 01:08]Napalm:we would do this
[2009-03-28 01:09]Napalm:ok i think i shall explain this step by step
[2009-03-28 01:09]Napalm:first we need to create a [paint]brush to fill the rect with
[2009-03-28 01:09]Napalm:HBRUSH hbYellow = CreateSolidBrush(RGB(255, 255, 0));
[2009-03-28 01:10]Napalm:quite straight forward
[2009-03-28 01:10]Napalm:we now need to select it into the HDC
[2009-03-28 01:10]Napalm:so we call SelectObject
[2009-03-28 01:10]Napalm:HBRUSH hbOld = (HBRUSH)SelectObject(hdc, hbYellow);
[2009-03-28 01:10]Napalm:if you select in a brush it will return the old brush
[2009-03-28 01:11]Napalm:now before you destroy a HDC you need to make sure it was in its original state
[2009-03-28 01:11]Napalm:so we save the old brush
[2009-03-28 01:11]Napalm:and once we are done painting we select the old brush back in
[2009-03-28 01:12]Napalm:HPEN hpRed2 = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
[2009-03-28 01:12]Napalm:HPEN hpOld = (HPEN)SelectObject(hdc, hpRed2);
[2009-03-28 01:12]Napalm:so that would create a 1 pixel solid red pen
[2009-03-28 01:12]Napalm:which will be used to draw the border to our rectangle
[2009-03-28 01:13]Napalm:so we
[2009-03-28 01:13]Napalm:Rectangle(10, 10, 20, 20);
[2009-03-28 01:13]Napalm:to perform the action
[2009-03-28 01:13]Napalm:this paints to the HDC
[2009-03-28 01:13]Napalm:ths means it actually modifies the pixels in the currently selected bitmap
[2009-03-28 01:14]Napalm:as i said before HDC is a collection of objects, this also means it contains a link to the bitmap where you want to perform your modifications
[2009-03-28 01:14]Napalm:after we have called Rectangle we want to reset the state of the HDC and return things to normal
[2009-03-28 01:15]Napalm:DeleteObject(SelectObject(hdc, hpRed2));
[2009-03-28 01:15]Napalm:DeleteObject(SelectObject(hdc, hbOld));
[2009-03-28 01:15]Napalm:hpOld
[2009-03-28 01:15]Napalm:my bad
[2009-03-28 01:15]Napalm:so as you can see the SelectObject does a nice thing here
[2009-03-28 01:16]Napalm:it returns the current brush/pen/object handle to the us which we pass back on to DeleteObject
[2009-03-28 01:16]Napalm:we could also call SelectObject and ignore the return value
[2009-03-28 01:17]Napalm:DeleteObject(hpRed2); DeleteObject(hbYellow);
[2009-03-28 01:17]Napalm:and do that
[2009-03-28 01:17]Napalm:but either way, no difference
[2009-03-28 01:17]Napalm:any questions so far? or has everyone died of bordem?
[2009-03-28 01:18]eth0:ACTION BRILLIANT!
[2009-03-28 01:18]Unknown:good stuff
[2009-03-28 01:18]TeraBiT:nope not died of boredom, really interesting stuff this is, and you're good at explaining them ^^
[2009-03-28 01:18]src:yeah learning alot
[2009-03-28 01:18]TeraBiT:explaining it*
[2009-03-28 01:18]Unknown:yeah but gonna haev to read the logs...
[2009-03-28 01:18]Napalm:ok, so
[2009-03-28 01:18]TeraBiT:wee vista back on
[2009-03-28 01:18]Napalm:lets see now
[2009-03-28 01:19]Napalm:so back to the example program http://www.netcore2k.net/downloads/glassbuttons_src.zip
[2009-03-28 01:19]Napalm:wait, hmm.. going to light up a smoke
[2009-03-28 01:20]Napalm:so wow ive been talking awhile
[2009-03-28 01:20]ABK:btw before you kick off again
[2009-03-28 01:20]ABK:31<ABK>30 what compiler? MSVC++?
[2009-03-28 01:20]Napalm:MSVC6
[2009-03-28 01:20]ABK:ahh 2008 version won't work?
[2009-03-28 01:20]Napalm:but any MSVC compiler will work, also the intel compiler should work
[2009-03-28 01:20]ABK:it DID compile it
[2009-03-28 01:20]Napalm:yes ABK, start a unmanaged C++ project
[2009-03-28 01:20]ABK:okay
[2009-03-28 01:21]Napalm:windows application
[2009-03-28 01:21]Napalm:and then add the source files to the blank project
[2009-03-28 01:21]Napalm:should compile
[2009-03-28 01:22]ABK:unamanged?
[2009-03-28 01:22]ABK:anad what kinda windows app? sorry for beign such a newbie at this but it's not jsut one windows app template
[2009-03-28 01:22]ABK:and*
[2009-03-28 01:23]ABK:'Empty Project'?
[2009-03-28 01:23]ABK:that one?
[2009-03-28 01:23]Napalm:you'll just have to try and see
[2009-03-28 01:23]Napalm:i dont have 2008 in front of me and cant say
[2009-03-28 01:23]ABK:ahh
[2009-03-28 01:24]Napalm:ok, any questions about GDI?
[2009-03-28 01:24]Napalm:anyone
[2009-03-28 01:24]Napalm:ok, onward
[2009-03-28 01:25]Napalm:so.. i suppose we can call this the second half
[2009-03-28 01:25]Napalm:so back to WinMain and we call Create
[2009-03-28 01:25]Napalm:of our new TestWindow class
[2009-03-28 01:26]Napalm:this creates a actual window on the screen we can communiate with
[2009-03-28 01:26]Napalm:the Create function is on BaseWindow
[2009-03-28 01:26]Napalm:lets take a look
[2009-03-28 01:26]Napalm:so, we call RegisterClassEx to register the base properties of our new window
[2009-03-28 01:27]Napalm:but, the class-names are application or system global
[2009-03-28 01:27]Napalm:so what happens when we have already registered it, RegisterClassEx fails
[2009-03-28 01:27]Napalm:so we check to see if the class exists with GetClassInfoEx
[2009-03-28 01:28]Napalm:if it doesnt exist things when bad so we return NULL and this will cause our code in WinMain to bring up a MessageBox to the user to let them know of that fact
[2009-03-28 01:28]Napalm:if all went well we call CreateWindowEx
[2009-03-28 01:29]Napalm:this function does not return until your window has processed the WM_NCCREATE and WM_CREATE (NC = non-client)
[2009-03-28 01:29]Napalm:the CreateWindowEx function itself contains a "message pump" itself to handle the starting messages for the window
[2009-03-28 01:30]Napalm:so if we scroll back to the top of BaseWindow to its constructor we can see the class properties
[2009-03-28 01:30]Napalm:as you can see we define BaseWindow::WndProc as our procedure and we also say that each window is given some extra bytes of storage space
[2009-03-28 01:31]Napalm:by the sizeof(LONG)
[2009-03-28 01:31]Napalm:this will let us store a pointer of our class instance, more on that later
[2009-03-28 01:31]Napalm:we setup some basic things like default icon and mouse cursor
[2009-03-28 01:32]Napalm:the sizeof(LONG) is 32bit so this wont work on 64bit systems
[2009-03-28 01:32]Napalm:we need to update the code to work on both, we can do that by replacing LONG with LONG_PTR
[2009-03-28 01:32]Napalm:windows sets the correct type size when being compiled as 64bit then
[2009-03-28 01:33]Napalm:the reason i have not done this in the code is that a lot of you dont have the PSDK (Platform Software Development Kit) which i suggest you all get and stop relying on the MSDN for API doc
[2009-03-28 01:33]Napalm:since the PSDK also gives you updated librarys and headers
[2009-03-28 01:34]Napalm:so back to the top of this source files BaseWindow.h
[2009-03-28 01:34]Napalm:and youi can see we define a couple of virtual functions
[2009-03-28 01:35]eth0:so will your code work on a 64bit system
[2009-03-28 01:35]Napalm:yes, if compiled as 32bit app
[2009-03-28 01:35]eth0:ahh ok
[2009-03-28 01:36]Napalm:you need to change the types so that we have room to store the 48bit addressing used by windows x64
[2009-03-28 01:36]Napalm:so back to the virtual functions
[2009-03-28 01:36]Napalm:these can be overridden by derived classes
[2009-03-28 01:37]Napalm:if a virtal function pointer member is declared as = 0 it means it has no pointer and therefore must be overridden
[2009-03-28 01:37]Napalm:futher on we declare a static WndProc "inside" our class
[2009-03-28 01:38]Napalm:but because its static it is global
[2009-03-28 01:38]Napalm:this is a requirement since a member functions uses the 'thiscall' calling convention where ECX contains the class pointer
[2009-03-28 01:38]Napalm:and windows WNDPROC type defines a windows procedure as a 'stdcall' calling convention function
[2009-03-28 01:39]Napalm:so, we need to translate this fact so we can handle the messages inside our class
[2009-03-28 01:39]Napalm:this is a simple trick
[2009-03-28 01:40]Napalm:because we declare the WndProc inside our class definition we are essentially telling the compiler it has the 'friend' qualifier and therefore can access protected members
[2009-03-28 01:40]Napalm:so when we receive a message it comes to our BaseWindow::WndProc function
[2009-03-28 01:40]Napalm:as you can see we need to be able to get a pointer to the class
[2009-03-28 01:41]Napalm:we do this with GetWindowLong to access our 'window extra byte' storage
[2009-03-28 01:41]Napalm:the second parameter to the function is the offset in the byte storage
[2009-03-28 01:41]Napalm:windows returns a dword from that address
[2009-03-28 01:41]Napalm:GetWindowLong is only 32bit safe
[2009-03-28 01:42]Napalm:we need to use GetWindowLongPtr if we want this code to compiler as 64bit
[2009-03-28 01:42]Napalm:and/or 32bit
[2009-03-28 01:42]Napalm:we then proceed to handle WM_NCCREATE because this is the first valid message we want
[2009-03-28 01:43]Napalm:we then cast the lParam as a CREATESTRUCT which contains the LPVOID we passed in CreateWindowEx
[2009-03-28 01:43]Napalm:if you noticed the last parameter to CreateWindowEx is the 'this' pointer for the current class
[2009-03-28 01:43]Napalm:now we have the pointer we need to set the bytes for the first and only time
[2009-03-28 01:44]Napalm:'extra window bytes' i should say
[2009-03-28 01:44]Napalm:we then update the LPVOID to our hWnd so we can store it later in m_hWnd
[2009-03-28 01:44]Napalm:as i said before this is a static function so we cant access m_hWnd
[2009-03-28 01:45]Napalm:if we have a pointer we can then execute member functions of our class because we (the WndProc function) qualifies as a 'friend' to the class
[2009-03-28 01:45]Napalm:so we hand off the message to PreHandleMessage which keeps our m_hWnd and m_rcClient variables up to date
[2009-03-28 01:46]Napalm:and then we forward that same message to the overridden HandleMessage function
[2009-03-28 01:46]Napalm:this is defined in both TestWindow.h and GlassButton.h
[2009-03-28 01:47]Napalm:the HandleMessage function can decided where it wants to handle any message and if it doesnt then the message gets post-processed by PostHandleMessage
[2009-03-28 01:47]Napalm:this will hand off to our own default actions
[2009-03-28 01:47]Napalm:in this case WM_PANT and WM_PRINTCLIENT
[2009-03-28 01:48]Napalm:the importance of handling WM_PRINTCLIENT and not just WM_PAINT is that AnimateWindow and other windows api's might need to paint your window to a HDC they own
[2009-03-28 01:48]Napalm:back on topic
[2009-03-28 01:48]Napalm:if its any other message we dont want to handle in a specific case we pass it on to DefWindowProc
[2009-03-28 01:49]Napalm:that concludes BaseWindow.h
[2009-03-28 01:49]Napalm:so on to TestWindow.h our "Main Window"
[2009-03-28 01:50]Napalm:here you see we override some of the default properties of the class definition
[2009-03-28 01:50]Napalm:the style and exstyle are most important
[2009-03-28 01:50]Napalm:this defines how our window is to be displayed
[2009-03-28 01:51]Napalm:see GlassButton.h for an example of a child style definition
[2009-03-28 01:51]KOrUPt:you know it sucks that i missed the start of this presentation, i'll read over the logs afterward
[2009-03-28 01:51]Napalm:np
[2009-03-28 01:51]KOrUPt:sorry for interrupting, continue...
[2009-03-28 01:51]Napalm:ok, so im not going to explain all the code
[2009-03-28 01:52]Napalm:i only wanted to explain the details of BaseWindow.h
[2009-03-28 01:52]Napalm:but the comments should explain most of the code
[2009-03-28 01:52]Napalm:on OnCreate we initalise our GlassButtons
[2009-03-28 01:53]Napalm:we return -1 on failure and this forces CreateWindowEx to also fail and return NULL and again this would then display a MessageBox in WinMain
[2009-03-28 01:53]Napalm:ive also created a small helper class called ResImage
[2009-03-28 01:54]Napalm:this lets you load up a JPEG/GIF/ICON/BMP whatever from resource and use it as-if it was a HBITMAP in your GDI operations
[2009-03-28 01:55]Napalm:we use WM_NCDESTORY aka OnNcDestroy instead of WM_DESTORY because WM_DESTORY is sent to use before our child windows and we dont really want to go and delete the class instances of our glassbuttons while the windows are still actibe
[2009-03-28 01:55]Napalm:active
[2009-03-28 01:55]Napalm:PostQuitMessage tells GetMessage to terminate our message pump loop
[2009-03-28 01:55]Napalm:in WinMain
[2009-03-28 01:56]Napalm:the value of its parameter is put in the wParam member of the MSG msgPump; structure in WinMain and this is what we return
[2009-03-28 01:56]Napalm:so if we have a explicit failure we could make a function which uses PostQuitMesage(ERROR_CODE) so we known immediate what caused the problem
[2009-03-28 01:57]Napalm:the rest of the message handlers in this class are quite simple
[2009-03-28 01:57]Napalm:further down we reach OnPaint
[2009-03-28 01:58]Napalm:this as you can see stretches the image we loaded via the HDC cast of the ResImage class
[2009-03-28 01:58]Napalm:SelectFont and SelectBitmap and its friends are macros in windowsX.h
[2009-03-28 01:59]Napalm:they simply fake SelectObject with casts
[2009-03-28 01:59]Napalm:it makes things easier to read, thats all
[2009-03-28 01:59]Napalm:as you can see, i draw the status text twices at a 1x1 offset so we get a slight black shadow
[2009-03-28 01:59]Napalm:it makes the text easier to read in the center
[2009-03-28 01:59]Napalm:and the OnClose handles the X button of the window
[2009-03-28 02:00]Napalm:this animates and destroys our window we then receive a WM_DESTORY and we call PostQuitMessage to exit our application
[2009-03-28 02:00]Napalm:ok... part 3
[2009-03-28 02:00]Napalm:lol
[2009-03-28 02:00]Napalm:what you all like
[2009-03-28 02:01]Napalm:GlassButton.h
[2009-03-28 02:01]Napalm:this is not a sub-classed button we re-implement the mouse handling and keyboard input
[2009-03-28 02:01]Napalm:this is so we can tab between buttons and use the space key to press the button
[2009-03-28 02:01]Napalm:this is quite essential for accessiblity
[2009-03-28 02:02]Napalm:same as before really
[2009-03-28 02:02]Napalm:we initalise the vars
[2009-03-28 02:02]Napalm:the 0xB28DBDFF is ARGB thats Alpha, Red, Green, Blue
[2009-03-28 02:02]Napalm:standard 32bit color definition
[2009-03-28 02:03]Napalm:this is our default blue coloured glow
[2009-03-28 02:03]Napalm:further down we give the public option to change the glow
[2009-03-28 02:03]Napalm:and handle the messages
[2009-03-28 02:04]Napalm:we handle WM_GETDLGCODE because we might want to place our button in a dialog
[2009-03-28 02:04]Napalm:im guessing you all have read the code by now
[2009-03-28 02:04]Napalm:can anyone note some further changes?
[2009-03-28 02:04]Napalm:well at the moment the control does not handle these things
[2009-03-28 02:05]Napalm: + Enable state (to show the button as disabled / greyed out) so it cant be clicked
[2009-03-28 02:05]Napalm: + perhaps the ability to set an icon to the button
[2009-03-28 02:06]Napalm: + also it should pay attention to the window styles and react to the Default push button and default cancel button styles
[2009-03-28 02:06]Napalm:this would let use be used for pressing Enter or Escape on a dialog
[2009-03-28 02:06]Napalm:ive commented this alot
[2009-03-28 02:07]Napalm:all of the mouse code maintains the state of the button and reacts to the mouse changes
[2009-03-28 02:07]Napalm:the glow which i guess you all like
[2009-03-28 02:07]Napalm:is achieved by the use of a Timer
[2009-03-28 02:07]Napalm:windows maintains the timer and we call SetTimer and KillTimer to manage it
[2009-03-28 02:08]Napalm:when the time for the timer elapses in this case 10ms (about the lowest pratical resolution) we get a WM_TIMER message
[2009-03-28 02:09]Napalm:we handle that message to change the "glow level" which is a floating point percentage of how much to alpha the glow color
[2009-03-28 02:09]Napalm:the OnTimer does the hard work here
[2009-03-28 02:09]Napalm:it maintains the level of glow
[2009-03-28 02:10]Napalm:so if the mouse moves out of the window (m_bMouseHover == FALSE) we decrement the glow
[2009-03-28 02:10]Napalm:this way the glow doesnt jump around
[2009-03-28 02:10]Napalm:now
[2009-03-28 02:10]Napalm:on to OnSize
[2009-03-28 02:10]anubis:wouldn't it be better to use WM_MOVE and TrackMouseEvent?
[2009-03-28 02:11]Napalm:WM_MOVE is when the window moves and not the mouse moves
[2009-03-28 02:11]anubis:or WM_MOUSEMOVE :|
[2009-03-28 02:11]Napalm:i do use MouseMove
[2009-03-28 02:11]Napalm::P
[2009-03-28 02:11]Napalm:as i said before our non-client area and client-area are rectangles
[2009-03-28 02:11]Napalm:but we have rounded rectangles to our windows?
[2009-03-28 02:12]Napalm:this is because we set the Window Region
[2009-03-28 02:12]Napalm:a region can be any shape or size
[2009-03-28 02:12]Napalm:its almost like a mask
[2009-03-28 02:12]Napalm:the window is still rectangle
[2009-03-28 02:12]Napalm:its just windows ignores things outside the region
[2009-03-28 02:13]Napalm:we could even place a "hole" inside our region and we would have a "hole" in our window
[2009-03-28 02:13]Napalm:this would not be deseriable because we wouldnt be able to paint there
[2009-03-28 02:13]Napalm:we could still have the window underneath display though, but that would cause flicker
[2009-03-28 02:14]Napalm:we trick the user into thinking our window is transparent
[2009-03-28 02:14]Napalm:because no child window on a windows system can have a transparency
[2009-03-28 02:14]Napalm:its all a shame
[2009-03-28 02:14]Napalm:we copy what would have been behind our window from the parent onto our window
[2009-03-28 02:14]Napalm:this is handled by the last function in our class
[2009-03-28 02:14]Napalm:more on that later
[2009-03-28 02:15]Napalm:the OnSize sets the region
[2009-03-28 02:15]Napalm:so that we dont get WM_MOUSEMOVE and other messages when the mouse is on the corner areas
[2009-03-28 02:15]Napalm:this is because essentially those corners our now part of the parent and not us
[2009-03-28 02:16]Napalm:also note that after you call SetWindowRgn the HRGN you give it is OWNED by windows
[2009-03-28 02:16]Napalm:you must not reuse it or destory it
[2009-03-28 02:16]Napalm:destroy
[2009-03-28 02:17]Napalm:this is different to the SelectClipRgn api in which a copy of your region is selected in and you still need to free your original
[2009-03-28 02:18]Napalm:you also need to call SelectClipRgn with NULL so that the copy of the original is destroyed
[2009-03-28 02:18]Napalm:now onward
[2009-03-28 02:18]Napalm:nearly done
[2009-03-28 02:18]Napalm:Redraw is a simple helper function to save code since we want to redraw the control a few times
[2009-03-28 02:18]Napalm:like when the state changes
[2009-03-28 02:19]Napalm:the m_bCacheDirty flag tells the WM_PAINT handler to destory the old image and use a new one
[2009-03-28 02:19]Napalm:since WM_PAINT will not redraw the control but reuse the cached copy
[2009-03-28 02:19]Napalm:this is used to save processor time
[2009-03-28 02:19]Napalm:lets say a window is above a button
[2009-03-28 02:20]Napalm:the window needs to be redrawn when it is uncovered
[2009-03-28 02:20]Napalm:our app would use the cached copy and not repaint it
[2009-03-28 02:21]Napalm:the RedrawWindow is passed with the UPDATENOW which means the WM_PAINT handler is called before the RedrawWindow function returns
[2009-03-28 02:21]Napalm:this is important
[2009-03-28 02:21]Napalm:this is so that actions like clicking the button are action immediatly
[2009-03-28 02:21]Napalm:if we were to simply invalidate the window (this tells windows it needs to repaint us)
[2009-03-28 02:22]Napalm:it might take a while to process
[2009-03-28 02:22]Napalm:since lots of other messages might be in our message queue
[2009-03-28 02:22]Napalm:and also because WM_PAINT is a low priorty message
[2009-03-28 02:22]Napalm:priority
[2009-03-28 02:22]Napalm:on the the big one
[2009-03-28 02:23]Napalm:OnPaint
[2009-03-28 02:23]Napalm:this does all the hard work
[2009-03-28 02:23]Napalm:Here is where the GDI+ code starts
[2009-03-28 02:23]Napalm:and yes, GDI+ has a C API which you can use instead of the GDI+ C++ classes
[2009-03-28 02:24]Napalm:does anyone want any explainations on this code
[2009-03-28 02:24]Napalm:or do the comments do it enough
[2009-03-28 02:24]Napalm:?
[2009-03-28 02:25]Napalm:i guess not, or everyone have fallen asleep
[2009-03-28 02:25]Napalm:either way i am continuing for the log
[2009-03-28 02:25]src:i think the comments are suffecient
[2009-03-28 02:25]KOrUPt::)
[2009-03-28 02:25]Kenaneo:sure on
[2009-03-28 02:26]Napalm:in this function we take the State flags we previously set and paint the button correctly
[2009-03-28 02:26]Napalm:remember we are drawing to a bitmap
[2009-03-28 02:26]Napalm:so there is no-such thing as layers
[2009-03-28 02:26]Napalm:we build up the image from back to front
[2009-03-28 02:26]Napalm:so we start with the background and add things on top
[2009-03-28 02:27]Napalm:all hex color codes are ARGB
[2009-03-28 02:27]Echo:yeah i figured
[2009-03-28 02:28]Napalm:the glow is calculated by taking the original color and shifting out the alpha and mutipling it by our alpha level
[2009-03-28 02:28]Napalm:this means if our glow color has a 50% alpha level
[2009-03-28 02:28]Napalm:our glow range is 0-50%
[2009-03-28 02:28]Napalm:100% glow leve is 50% color
[2009-03-28 02:28]Napalm:*level
[2009-03-28 02:29]Napalm:next we get the window text and draw it center of the button
[2009-03-28 02:29]Napalm:we could modify this so that if a private class member of an icon is set we draw an icon to the left of the text
[2009-03-28 02:29]Napalm:this icon could even be 32bit so it has a alpha channel
[2009-03-28 02:30]Napalm:as you can see we clip all graphics to the inside of the button so we dont draw over our borders
[2009-03-28 02:30]Napalm:the CreateRoundRectPath function after onPaint is needed because for some odd reason GDI+ has no AddRoundRect member on the GraphicsPath class
[2009-03-28 02:31]Napalm:in standard GDI we can use the CreateRoundRectRgn API
[2009-03-28 02:31]Napalm:so if your control/window is GDI only that is perfect since we can clip to regions in GDI
[2009-03-28 02:32]Napalm:the DrawRoundRect is just to get a nice alignment in the anti-aliased borders
[2009-03-28 02:32]Napalm:without that the borders are so close they might overlap and destory each other
[2009-03-28 02:32]Napalm:the PaintParentBackground function does a neat trick
[2009-03-28 02:33]Napalm:we pass it a HDC
[2009-03-28 02:33]Napalm:we set the window origin
[2009-03-28 02:33]Napalm:now this is not Window as in a screen object
[2009-03-28 02:33]Napalm:this is 'window' used in the display context of the word
[2009-03-28 02:33]Napalm:'window' of an area
[2009-03-28 02:34]Napalm:lets say the orgin was 10, 10 normally its 0, 0
[2009-03-28 02:34]Napalm:this means all drawing operations gets translated and 10 pixels are added to the x and y
[2009-03-28 02:34]Napalm:so if i called the GDI operation LineTo(hdc, 10, 10);
[2009-03-28 02:34]Napalm:it actually draws a line from 10, 10 to 20, 20
[2009-03-28 02:35]Napalm:we use this to our advantage
[2009-03-28 02:35]Napalm:we set the origin to our location on the parent window
[2009-03-28 02:35]Napalm:we use MapWindowPoints to do that
[2009-03-28 02:35]Napalm:and then we Create a rectangle region for our client size (our width and height) and then clip all further painting to our HDC to that area
[2009-03-28 02:36]Napalm:this means when we call the parent WM_PRINTCLIENT it only uses the portion of our width and height at our location on the parent
[2009-03-28 02:37]Napalm:we then call WM_PRINTCLIENT and reset everything
[2009-03-28 02:37]Napalm:wow
[2009-03-28 02:37]Napalm:that was a lot of typing
[2009-03-28 02:37]Napalm:im sure i have RSI
[2009-03-28 02:37]Napalm:lol
[2009-03-28 02:37]Napalm:so
[2009-03-28 02:37]Napalm:lets get this long ass lecture over with
[2009-03-28 02:37]Napalm:Q and A time
[2009-03-28 02:37]Napalm:ask away and i will do my best to answer
[2009-03-28 02:37]anubis::D
[2009-03-28 02:38]anubis:what's rsi
[2009-03-28 02:38]Napalm:http://en.wikipedia.org/wiki/Repetitive_strain_injury
[2009-03-28 02:38]Napalm:now how about some questions to do with the project?
[2009-03-28 02:38]Napalm:anything?
[2009-03-28 02:39]KOrUPt:i'll likely have some tomorrow morning once i finish reading over the (long) log
[2009-03-28 02:39]Napalm:wow, i must have done a good job explaining if there are no questions
[2009-03-28 02:39]anubis:yuz
[2009-03-28 02:39]Napalm:my thoughts are just that everyone as got bored
[2009-03-28 02:39]src:twas over 500 lines :O
[2009-03-28 02:39]Napalm:and left
[2009-03-28 02:39]Napalm:lol
[2009-03-28 02:39]Echo:nope, we are here
[2009-03-28 02:39]src:informative, thanks Napalm
[2009-03-28 02:39]Napalm:i suppose i better stop the log bot
[2009-03-28 02:39]Kenaneo:me still checking the code
[2009-03-28 02:40]Napalm:ah
[2009-03-28 02:40]Napalm:hmm, there is another topic i could cover
[2009-03-28 02:40]Echo:hopefully everyone can understand that by using classes as a container the code stays extremly organized
[2009-03-28 02:40]Napalm:before i close the log bot
[2009-03-28 02:40]Napalm:if you are all want to listen to more?
[2009-03-28 02:41]KOrUPt:go ahead
[2009-03-28 02:41]Echo:what is the topic
[2009-03-28 02:41]src:mhm
[2009-03-28 02:41]Napalm:Thunking
[2009-03-28 02:41]Napalm:http://en.wikipedia.org/wiki/Thunking
[2009-03-28 02:41]Napalm:we can use a small piece of assembly code instead of our WndProc
[2009-03-28 02:41]Echo:do it
[2009-03-28 02:42]Napalm:and it would alot more efficent then using the 'extra window bytes' as storage
[2009-03-28 02:42]Napalm:the idea goes like this
[2009-03-28 02:42]Napalm:we great a small asm code like:
[2009-03-28 02:42]KOrUPt:create*
[2009-03-28 02:42]Napalm:lea ecx, this; mov eax, proc; jmp eax
[2009-03-28 02:43]Napalm:args its late and im sluring my words
[2009-03-28 02:43]Napalm:lol
[2009-03-28 02:43]Napalm:ok
[2009-03-28 02:43]Napalm:so the asm code above would move our class pointer into ecx
[2009-03-28 02:43]Napalm:we then move the true method address for our private function in to eax and call it
[2009-03-28 02:44]Napalm:this means we have simulated a 'thiscall' function call
[2009-03-28 02:44]Napalm:so if we allocate a piece of executable memory using virtualalloc
[2009-03-28 02:45]Napalm:insert our machine code and pointers and then set the classes WndProc to that
[2009-03-28 02:46]Napalm:well, we would set it on a per-window basis with SetWindowLongPtr(hWnd, GWLP_WNDPROC)
[2009-03-28 02:46]Napalm:this means, we essentially call our member procedure directly and handle the messages
[2009-03-28 02:47]Napalm:this trick can be done with any other CALLBACK api function in windows
[2009-03-28 02:47]Napalm:so for say a static timer from SetTimer
[2009-03-28 02:47]Napalm:or even the result of a call to waveOutOpen
[2009-03-28 02:47]Napalm:all sorts
[2009-03-28 02:47]Napalm:quite a nifty idea
[2009-03-28 02:47]Napalm:anyways, thats all
[2009-03-28 02:48]Napalm:any questions before i stop the log bot?
[2009-03-28 02:48]falkman:ACTION applauds.
[2009-03-28 02:48]Napalm:ACTION bows
[2009-03-28 02:49]Napalm:ok, bot stopping