Showing posts with label embeded. Show all posts
Showing posts with label embeded. Show all posts

Saturday, July 24, 2010

Windows messaging system

How I understand windows messaging system

I have taken a look to MFC, WTL frameworks and desided to explain some moments aligned to window creation and user interaction on Windows API level

Creating  a Window

To create window in Windows OS you call CreateWindow(className,...)
There is a enum of predefined classes
COMBOBOX, BUTTON, STATIC, LISTBOX and other default classes

As far as thay are already pressent in the system they asosiated with WindowProc. Actually every window class is asociated with windowProc inside OS.
What is window proc? it is just a function like below


INT_PTR CALLBACK MyDialog_DialogProc( HWND hwnd,
UINT messageId,
WPARAM wParam,
LPARAM lParam )


WindowProc is responsible for the window message processing. Thats why BUTTON for example looks like button :) , so to create a dialog not from window resources you need. To understand how OS GUI works lets create a dialog manually and not using resource file for that.


Creating Dialog window not from recources


1. register class

WNDCLASS wndClass = {0};
wndClass.lpfnWndProc = (WNDPROC)MyDialog_DialogProc;
wndClass.lpszClassName = L"DIALOG";
ATOM atom = RegisterClass(&wndClass);
HWND dialogHwnd = CreateWindow(L"DIALOG", L"MyDlg", ~WS_DLGFRAME &    ~WS_CLIPSIBLINGS, 10,10, 200,200, NULL, (HMENU)0, instance, 0); 

2. write a WindowProc

INT_PTR CALLBACK MyDialog_DialogProc( HWND hwnd,
UINT messageId,
WPARAM wParam,
LPARAM lParam )
{
if (messageId == WM_CREATE)
{
     // create button
   HINSTANCE hInstance = GetModuleHandle(NULL);
     HWND myButton = CreateWindow(L"BUTTON", L"ClickMe"
           , WS_CHILD, 10,10, 100,20, hwnd
           ,(HMENU)1, hInstance,0);
     if (!myButton)
     {
         // log error
     }
         ShowWindow(myButton, SW_SHOWNORMAL); 
  // create othe controls if there is a need!
  return TRUE;
}
return DefWindowProc( hwnd,  messageId, wParam, lParam); 
}

You can change this default WindowProc and this process is so calling subclassing
There is a lot of windows messages so if you don't need (or you don't want) to process all of them you need to call oldWindowProc to process messages that your new WindowProc doesn't process

I found that class "DIALOG" is not a default class in windows. This class creates when you are going to create a dialog based on recource file. When you create dialog from recource (using CreateDialog for example) this function register dialog class read resource file read styles inside dialog and raise WM_INITDIALOG and othe windows messages (WM_FONT is GWS_FONT defined) and after that call ShowWindow (if GWS_VISIBLE is defined)
all this steps is strictly synchronous because SendMessage is sync function.
How windows looks depends on window class and on windows style

Message handling 

As you may know some messages are received in thread queue others processed directly in WindowProc so you will never get WM_SIZE using GetMessage() or similar function

But messages from mouse and keybord will be sent to system queue
for example for erlier created messages in the same thread we use:


MSG msg;
while (GetMessage(&msg,0,0,0))
{
TCHAR buffer[MAX_PATH] = {0};
TCHAR windowName[MAX_PATH] = {0};
GetWindowText( msg.hwnd, windowName, MAX_PATH);
swprintf(buffer,L"Handle [0x%X] WindowName [%s] Message: [0x%X] \n",msg.hwnd, windowName , msg.message);
OutputDebugString(buffer);
DispatchMessage(&msg);
}


GetMessage Log:

Handle [0x0] WindowName [] Message: [0xC0B1] 
Handle [0x0] WindowName [] Message: [0xC0B1] 
Handle [0x60878] WindowName [MyDlg] Message: [0xF]  // WM_PAINT
Handle [0x60870] WindowName [ClickMe] Message: [0xF]  // WM_PAINT
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B7] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B9] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B9] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B9] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B9] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B9] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6] 
Handle [0x6086E] WindowName [CicMarshalWndAJCB] Message: [0xC0B6]


from the log we can see that only WM_PAINT message we receive from GetMessage. Messages with 0 handle are messages not aligned to windows. There is also a CicMarshalWndAJCB but we didn't create window with such mane. I created only two windows "ClickMe" and "MyDlg" so what is "CicMarshalWndAJCB" for?

of cource when I move my mouse to that window I receive all mouse/keyboard input messages like WM_MOUSEMOVE WM_KEYDOWN and othe hardware messages

In  the Internet I also could not find any information about that window , so if someone reading this could help, please do

To complete  this article I put log in dialog window proc to better understand what messages come  first

WindowProc Log



Handle [0x3B086A] Message: [0x24]  //WM_GETMINMAXINFO
Handle [0x3B086A] Message: [0x81]  //WM_NCCREATE
Handle [0x3B086A] Message: [0x83]  //WM_NCCALCSIZE
Handle [0x3B086A] Message: [0x1]   //WM_CREATE
Handle [0x3B086A] Message: [0xD]   //WM_GETTEXT my call
Handle [0x3B086A] WindowName [MyDlg] Message: [0x1] //WM_CREATE we receive only one wm create but I put log just to be sure that windowname is MyDlg
Handle [0x3B086A] Message: [0x210] // WM_PARENTNOTIFY
Handle [0x3B086A] Message: [0x18]  //WM_SHOWWINDOW
Handle [0x3B086A] Message: [0x46]  // WM_WINDOWPOSCHANGING
Handle [0x3B086A] Message: [0x46]  // WM_WINDOWPOSCHANGING // this call from thread
Handle [0x3B086A] Message: [0x1C]  // WM_ACTIVATEAPP
Handle [0x3B086A] Message: [0x86]  // WM_NCACTIVATE
Handle [0x3B086A] Message: [0xD]   // WM_GETTEXT
Handle [0x3B086A] Message: [0x6]   // WM_ACTIVATE
Handle [0x3B086A] Message: [0x7]   // WM_SETFOCUS
Handle [0x3B086A] Message: [0x85]  // WM_NCPAINT
Handle [0x3B086A] Message: [0xD]   // WM_GETTEXT
Handle [0x3B086A] Message: [0x14]  // WM_ERASEBKGND !! I have handled it
Handle [0x3B086A] Message: [0x47]  // WM_WINDOWPOSCHANGED
Handle [0x3B086A] Message: [0x5]   // WM_SIZE
Handle [0x3B086A] Message: [0x3]   // WM_MOVE
Handle [0x3B086A] Message: [0x7F]  // WM_GETICON
Handle [0x3B086A] Message: [0x7F]  // WM_GETICON
Handle [0x3B086A] Message: [0x7F]  // WM_GETICON
Handle [0x3B086A] Message: [0xF]   // WM_PAINT
Handle [0x3B086A] Message: [0x135] // WM_CTLCOLORBTN ClickMe send this message to parent


So this mechanism works very good
all other stuff and errors and a lot of complains alligned to higher level of API in user mode. Teoretically it is possible to rewrite user mode API to have very simple and ea sy to use operating system. I think this is might be done by 3rd party vendows that works with Windows CE OS

Saturday, May 22, 2010

Nano-X window system

Recently I have worked in Linux environment with a great NanoX project
It is about 300k size. NanoX provide solution for timer support, windows management, user input.

To use Nano-X you need only gcc c/c++ compiler that it is included in many(most) Linux systems

Architecture:




Features:
- message based system
- small size
- simple API
- add/replace any keyboard/mouse/screen driver
- font support. It is possible to add Unicode TrueType fonts

Lets discuss how to use it:

To create nano-X window you need :


#include  "nano-x.h"
  
int main(int argv, char[][] argv)
{
   GR_WINDOW_ID wnd = 
     GrNewWindow( GR_ROOT_WINDOW_ID
                  , 0,0,100,100
                  , WINDOW_NO_BORDER
                  , FOREGROUND_COLOR
                  , BLACKGROUND_COLOR); // create a window

   gc = GrNewGC(); // create a graphic context


   //select events. you are able to select 
   //only that events that you need. this will boost your application  
   GrSelectEvents( wnd, GR_EVENT_MASK_ALL); 


   GrMapWindow( wnd ); // show window


   // you may create as many windows as you wish
   // there is only one message queue for all Nano-X windows


   GR_EVENT anEvent;
   while (true)
   {
     GrCheckNextEvent(&anEvent);
     if (anEvent.type == GR_EVENT_TYPE_NONE )
     {
       sleep(1); 
       continue;
     }
     if (HandleEvent(anEvent) == NEED_TO_EXIT) break; 
   }
   // close all handles and exit
   GrUnmapWindow(wnd); // hide window
   GrDestroyGC( gc ); //
   GrDestroyWindow( wnd ); 

}

Now you might understand nano-x weak side: 

  • Messages might not be synchronized. ( for example when you kill window but some messages that was in queue might come)
  • Timer messages might not work proper under some circumstances  (for example when you create a timer event, then change time in your system) 
  • Pure focus management (for example you can use GrSetFocus() then destroy window and then GrGetFocus() doesn't return you focus to a parent window like it is in MS Window OS,
  • Font support is available but you have to dig into sources to add it.