Saturday, December 26, 2009

Maya Shelf

Hold "CTRL + SHIFT + Element to add" to add icons to the custom shelf
Hold "SHIFT+ ALT+ Element to add" to add icons to the custom shelf in Linux

Wednesday, December 9, 2009

Compiling wxWidgets using mingw32-make

Some months ago I showed you how to compile wxWidgets using the ./configure method. Today I've tried to compile it using mingw32-make so here it is:

First let's set the path to our mingw and mingw32 bin directories:
set path=D:\MinGW\mingw\bin;c:\MinGW\mingw\mingw32\bin;
 
Next we enter in our WXWIDGETS\build\msw directory and type the following statement:
mingw32-make -f makefile.gcc SHARED=1 MONOLITHIC=1 BUILD=debug UNICODE=1
And that's it!
 

Wednesday, November 18, 2009

Raw Input Introduction Part 1: Keyboard Input

Since I've found very little information about Raw Input API on the net, I thought it could be of some help to write an article as an introduction to it. So here it is.
Let's get started!

Registering Raw Input Devices
The first thing we need to do is registering the input device we'd like our application to monitor.
The main and probably most important difference of Raw Input from DirectInput and standard Win32 messages, is that Raw Input can retrieve which device has sent the input and not just the input.
That means that if you have two keyboards connected, Raw Input will be able to recognise the input and which one of the two keyboards has sent it.
That's why we need to register our input devices.
Let's make a header file called RawInputUtils.h and write the following code:

void InitRawInput(HWND hWnd)
{
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = 0x01;
Rid[0].usUsage = 0x06;
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = hWnd;

if (RegisterRawDataInputDevices(Rid,1,sizeof(Rid[0])) == false)
{
  MessageBox(NULL, "Device Registration failed", "Error",MB_OK);
  return;
}
}

RAWINPUTDEVICE is a structure used to describe the input device we want to monitor. Its parameters are the following:
  • usUsagePage Top level HID usage page. For most HIDs the value is 0x01
  • usUsage Number indicating which type of device should be monitored. For keyboard the value is 0x06, for mouse it's 0x02. Here you can find a complete list of the possible values.
  • dwFlags Determine how the data should be handled. Here a complete list of the possible values.
  • hwndTarget Handle to the window which will monitor this device.
So what we have done here is:
  1. RAWINPUTDEVICE Rid[1]; We have declared an array of a single element that will hold a RawInputDevice structure that describes our device (in our case the keyboard).
  2. Rid[0].usUsage = 0x06; We specify that our device is a keyboard
  3. Rid[0].dwFlags = RIDEV_INPUTSINK; This means that our application will retrieve input even if it loses focus.
  4. Rid[0].hwndTarget = hWnd; We specifies the handle of the application window that will monitor our device. In our case the one we pass to the InitRawInput function.
After we have described our devices we need to register it:

if (RegisterRawDataInputDevices(Rid,1,sizeof(Rid[0])) == false) { //Error}

The RegisterRawDataInputDevices() function returns false if the device registration fails.
Its arguments are the following:
  1. pRawInputDevices Pointer to an array of RAWINPUTDEVICE structures that represent the devices we want to register (in our case we have just a single element, the keyboard)
  2. uiNumDevices Number of RAWINPUTDEVICE structures we have inside our RAWINPUTDEVICE array
  3. cbSize Size in bytes of a RAWINPUTDEVICE structure.
The next step is to call our InitRawInput() function somewhere inside our WinMain() functon so we can register our device for our application.
First of all, let's add an include to our RawInputUtils header we have just wrote.
Then add this code in the WinMain() function just after the ShowWindow() function call (don't worry if you don't get where you have to put it, you can find the complete source code at the bottom):


InitRawInput(hWnd);


The InitRawInput() call should have described our device and registered it. If nothing went wrong we can proceed further.

Retrieving raw input
Now, inside our WndProc() function we need to add the WM_INPUT case inside our switch(msg) statement:

case WM_INPUT:
{
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
.....

GetRawInputData() accept the following arguments:
  1. hRawInput Handle to the RAWINPUT structure containing the input data we want to process. This is provided by the lParam in WM_INPUT message.
  2. uiCommand Flag that sets whether to retrieve the input data or the header information from the RAWINPUT structure. Possible valures are RID_INPUT or RID_HEADER.
  3. pData  If we set it to NULL, the size of the buffer required to contain the data is returned in the pcbSize variable. Otherwise, pData must be a pointer to allocated memory that can hold the RAWINPUT structure provided by the WM_INPUT message.
  4. pcbSize A variable that returns or specifies the size of the data pointed by pData.
  5. cbSizeHeader Size of a RAWINPUTHEADER structure.
Once we called this function, our dwSize variable will correspond to the exact number of bytes needed to store the raw input data.
Now, we declare a pointer to the right amount of memory to store the rawinput data:

lpb = new BYTE[dwSize];

Next we call the GetRawInputData() function for the second time to ensure that lpb points to a right amount of memory to store the raw input data of dwSize size.

if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize,sizeof(RAWINPUTHEADER)) != dwSize)
{
//Error
}


Now we need to "cast" our lpb pointer to RAWINPUT structure which gives easy access to the data various members.

raw = (RAWINPUT*)lpb;

Processing raw input
First we check if the raw input data is of keyboard type:

if (raw->header.dwType == RIM_TYPEKEYBOARD)
{ 

Next we ensure to retrieve both system and non-system key down events:

if (raw->data.keyboard.Message == WM_KEYDOWN || raw->data.keyboard.Message == WM_SYSKEYDOWN)
{ 

Then we returns in the window title the key code of the key we press.

USHORT usKey;
usKey = raw->data.keyboard.VKey;
CHAR szTest[4];
_itoa_s((int)usKey,szTest,10);
SetWindowText(hWnd,szTest);
}
}
delete[] lpb;

This little example should show you the three main steps to follow to implement Raw Input inside your application.
Comments and questions are welcome.
Hope this article will be useful. Sorry for my bad style of coding ^^.
Until next time, cheers!

Source code:



Sunday, June 14, 2009

Setting up Eclipse + wxWidgets 2.8.10 + OpenGL

Ok, here's just a little update if you want to work with wxWidgets and OpenGL inside Eclipse.
It took me a while to figure out how to make Eclipse building my wxWidgets/OpenGL tests but the trick is easy now that I've found it! ^^
Here are the updated-opengl commands to paste into the Linker flags :

Debug Build
-lopengl32 -lglu32 `wx-config --debug=yes --static=no --libs std,gl`

Release Build
-lopengl32 -lglu32 `wx-config --debug=no --static=no --libs std,gl`

Setting up Eclipse + wxWidgets 2.8.10

After we have built our Debug and Release versions of wxWidgets now I show you how to setup wxWidgets with Eclipse.

Pre-Requisites
- Eclipse
(I prefer the C++ Developers version. It's lighter than the standard version, it comes with the CDT plugin already installed and it solved me some problems I had with the standard version with the CDT manually installed. You can download it here)
- MinGW + MSYS
- Both Debug/Release versions of wxWidgets

Debug Setup
1. Start Eclipse
2. Go to File --> New C++ Project
Under Project Type choose Executable --> Empty Project and under Toolchains select MinGW.
Name your project whatever you like and click Finish.
3. Right click on your project and click on Properties and check that Configuration set to Debug.
4. Go to C/C++ Build --> Tool Chain Editor and where it says Current builder select Gnu Make Builder
5. Go to C/C++ Build and unckeck Use default build command and where it says Build command type mingw32-make
6. Go to C/C++ Build --> Environment
Click on Add and where it says Name type PATH.
Where it says Value copy your wxWidgets Debug bin directory path (mine is D:\wx-Debug\bin)
7. Go to C/C++ Build --> Settings --> GCC C++ Compiler
Where it says Command paste this line: g++ `wx-config --debug=yes --static=no --cxxflags`
8. Go to C/C++ Build --> Settings --> MinGW C++ Linker
Where it says Command line pattern cut the variable ${FLAGS} and paste it at the end of the line.
9. Go to C/C++ Build --> Settings --> MinGW C++ Linker --> Miscellaneous
Where it says Linker flags paste this line: `wx-config --debug=yes --static=no --libs`

That should be all for the Debug setup.

Release Setup
Starting from step 3 of the Debug setup guide change it this way:

1. Check that Configuration is set to Release
2. Go to C/C++ Build --> Tool Chain Editor and where it says Current builder select Gnu Make Builder
3. Go to C/C++ Build and unckeck Use default build command and where it says Build command type mingw32-make
4. Go to C/C++ Build --> Environment
Click on Add and where it says Name type PATH.
Where it says Value copy your wxWidgets Release bin directory path (mine is D:\wx-Release\bin)
7. Go to C/C++ Build --> Settings --> GCC C++ Compiler
Where it says Command paste this line: g++ `wx-config --debug=no --static=no --cxxflags`
8. Go to C/C++ Build --> Settings --> MinGW C++ Linker
Where it says Command line pattern cut the variable ${FLAGS} and paste it at the end of the line.
9. Go to C/C++ Build --> Settings --> MinGW C++ Linker --> Miscellaneous
Where it says Linker flags paste this line: `wx-config --debug=no --static=no --libs`

Add a c++ source file and copy this source inside to test the building:

#include <wx/wx.h>


class MyApp : public wxApp
{
virtual bool OnInit();
};

IMPLEMENT_APP(MyApp)


class MyFrame : public wxFrame
{
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
};

enum
{
ID_Quit=1,
ID_About
};


bool MyApp::OnInit()
{
MyFrame *frame = new MyFrame(_T("Hello World"), wxPoint(50,50),
wxSize(450,350));

frame->Connect( ID_Quit, wxEVT_COMMAND_MENU_SELECTED,
(wxObjectEventFunction) &MyFrame::OnQuit );
frame->Connect( ID_About, wxEVT_COMMAND_MENU_SELECTED,
(wxObjectEventFunction) &MyFrame::OnAbout );

frame->Show(TRUE);
SetTopWindow(frame);
return TRUE;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame((wxFrame*)NULL,-1,title,pos,size)
{
// create menubar
wxMenuBar *menuBar = new wxMenuBar;
// create menu
wxMenu *menuFile = new wxMenu;
// append menu entries
menuFile->Append(ID_About,_T("&About..."));
menuFile->AppendSeparator();
menuFile->Append(ID_Quit,_T("E&xit"));
// append menu to menubar
menuBar->Append(menuFile,_T("&File"));
// set frame menubar
SetMenuBar(menuBar);

// create frame statusbar
CreateStatusBar();
// set statusbar text
SetStatusText(_T("Welcome to wxWindows!"));
}

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(TRUE);
}

void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
wxMessageBox(_T("wxWindows Hello World example."),_T("About Hello World"),
wxOK|wxICON_INFORMATION, this);
}


Let me know if you encounter any problems.
Thanks for reading.

Building WxWidgets on Windows with MinGW + MSYS

This is a short tutorial about how to get Debug and Release builds from wxWidgets sources.

Pre-Requisites:
- Windows 2000/XP (the commands should work on Linux too but I didn't test them yet)
- MinGW + MSYS
- latest stable wxWidgets release (at the time of this writing it's 2.8.10) downloadable here


Debug Build
1. Extract the source archive wherever you want
2. Start MSYS and get into the source directory (in my case cd d:/wxWidgets2.8.10)
3. Type ./configure --enable-shared --enable-debug --with-opengl --prefix=D:/wx-Debug

--enable-shared --> build wxWidgets as a shared library (or dynamic library if you prefer)
--enable-debug --> build a debug version of wxWidgets
--with-opengl --> enable OpenGL widgets (it is not mandatory if you don't plan to use OpenGL)
--prefix=D:/wx-Debug --> the directory where we want to install wxWidgets (it's not mandatory but it helps to make things cleaner)

After configure ends its duties, it should send you back a message about the configuration you choose.
4. Now type: make
and then: make install

Now you should have your wxWidgets Debug version installed.

Release Build
1. Get into your wxWidgets source directory again
2. Type ./configure --enable-shared --disable-debug --with-opengl --prefix=D:/wx-Release
3. Type make
and then make install

Next time I'll show you how to setup Eclipse with wxWidgets!
Stay tune and thanks for reading.