Search This Blog

Showing posts with label GUI and Shell. Show all posts
Showing posts with label GUI and Shell. Show all posts

Monday, September 7, 2009

Regions and Clipping Window to Custom Shapes (Win32 VC++)

Intro.

You might have noticed certain applications have window which differ from the standard, normal window with Rectangle shape, a Title bar, Size bar and System menu. Well, a most common example is the Windows Media Player which can be found on Windows XP versions. The Windows Media Player 9 series Installed by default on all Microsoft WindowsXP OS possesses a different appearence on screen, with a new window shape and appearence. You should also thought about how to make your application's window also customized and re-shaped like that. Well, thats a good idea when thinking about GUI and dressing up your application's window.

How to do.

Before getting into the code, lets learn about something about Window Regions. Well, when talking about regions some people may wonder what this "region" is. The "Region" we use here in a window is exactly whatthe name denotes. It can be a specific area of any defined shape. There is nothing strict that a region must be rectangle. A region can be sphere, elliptic or any other combined shape you desire.To apply a region to a window, you must first declare a region handle (HRGN), define the region with calls to CreateRectRgn, CreateEllipticRgn, or CreatePolygonRgn( Refer to MSDN for more Region API's ). Then combine your regions( only if you have multiple regions defined) into one region with calls to CombineRgn, and then apply the final region to your window with a call to SetWindowRgn.


A region is an object, so you should DeleteObject them when you are done with them. :-)


I'm going to demonstrate a sample window with two Regions. Both are elliptical regions and i combine both these regions to a single one. Finally, i clip or cut my window in shape of this new custom region. The WIndow shape is modified to a defined region by using SetWindowRgn() API.


Code.



HRGN hRegion1 = CreateEllipticRgn(0, 30 , 200, 200);
HRGN hRegion2 = CreateEllipticRgn(0, 180, 200, 200);

CombineRgn(hRegion1, hRegion1, hRegion2, RGN_OR);
SetWindowRgn(hWnd, hRegion1, true);

DeleteObject(hRegion1);
DeleteObject(hRegion2);

The RGN_OR flag set in CombineRgn() performs logical ORing operation with both the regions, and apply it to the Window using a call to SetWindowRgn().


Now, you have a strange window shape. Since there is no Title Bar and Standard Window Buttons, you cannot drag the Window over the screen or you cannot close or minimize it. So, you have to close the application from Debugger or from Task Manager in Windows. You can add custom buttons by your own for Close and Minimize operation or whatever you like in this window. Now, what's the deal with Dragging?


A window which cannot be dragged across the screen is unimaginable and will be weird. The Window's title bar which helps us to drag is clipped away. Dont worry, we have a solution say a trick.


We will trick the Window whenever a left mouseclick happens within the window region to convince it the click happened on its Title bar. So, when we click inside the window and drag, it will get dragged across the screen as if it were dragged by clicking its titlebar.
We'll need to add the following case to our message handler's switch:

case WM_LBUTTONDOWN:
SendMessage( hWnd, WM_NCLBUTTONDOWN, HTCAPTION, NULL );
break;

WM_LBUTTONDOWN is sent whenever the user presses the left mouse button while the mouse is over the window. So when we catch this message, we send a WM_NCLBUTTONDOWN message to the title bar (HTCAPTION), tricking it into thinking we clicked it. Remember, clipping window will not delete other parts of the window. So, the titlebar is still present but not visible and it still has a message handler waiting for processing messages.


PS : Feedbacks helps me to know and improve :=)

Thursday, July 30, 2009

How to make WindowsXP Taskbar Transparent using Win32 VC++


Intro.
Hi all, you should be familiar with soo many shellpacks and themes for WindowsXP floating around internet from its initial release. Its a good factor, WindowsXP can be skinned or themed. And, when the sucessor to Microsoft's NT 5.1 (XP), Windows Vista (NT version 6.0) came out, it came with translucent glass efects on Windows Taskbar and Titlebars. The theme guys were after translucency from the time right Microsoft Announced Vista. And, surprisingly enough, i also got some themes for WindowsXP which provided Translucent taskbar and titlebar makeing it a wonderful effect in WindowsXP. Well, in Transparency, what made my mind struck is the Taskbar of Windows Vista. The Theme makers had suceeded to imitate it exactly, and almost exactly in WIndowsXP. One of those themes i like is GlassXP, and another is Vistamizer. Okay, if they can make transparent Taskbar in WindowsXP, then definitely WindowsXP supports that feature. Now, I'm showing you how to achieve Taskbar transparency in WindowsXP using Visual C++ and Windows API's. Here comes the Alpha Blending function of Windows. From Windows version 200 onwards, you can control Alpha values of every window using SetLayeredWindowAttributes() API. And, there's no much bulky codes to do this... just a single API call can make a Taskbar transparent. This works with Windows2000(NT)+ Platforms only. This wont work in WIndows95/98/ME. :)

How to do.

The Microsoft WIndows versions ranging from 2000 onwards supports Alpha Blended transparency for a window. In Windows programming, each and every "Window" has its own properties as well as standard window properties and has a unique "classname". The Taskbar is also a window. So, we can surely use classname of Taskbar to find it as a window, identify and alphablend it. The classname of Windows Taskbar is "Shell_TrayWnd". So, first we will find a Window with classname "Shell_TrayWnd" using FindWindow() API call to retrieve the HWND or handle to the Window. Alpha Blending requires it to be done on "Layered Windows" or window created with WS_EX_LAYERED flag. We dont know whether taskbar is created with Layered attributes or not. Anyway, lets do it if its not. We use GetWindowLong() API with flag GWL_EXSTYLE and handle of taskbar, which will return a DWORD value representing style atributes of current Window(in our case, taskbar). We will Logically OR it with WS_EX_LAYERED and pass it to SetWindowLong() which will make the Window to set WS_EX_LAYERED flag along with its other style attributes. Okay, now we can call SetWindowLayeredAttributes() and pass in an Alpha value between 0 to 255 as we needed for the taskbar transparency. 0 makes the Taskbar/Window Completely transparent and it will be invisible. 255 makes the window Opaque. Here, i'm using 200 As Alpha value for my Taskbar. and I've used the WindowsXP's Silver color scheme as i feel it more good :)



Code.

Well, its time for some code :


 HWND hTaskBar;
 DWORD dwStyle;


  hTaskBar = FindWindow( _T( "Shell_TrayWnd" ), 0 );
  dwStyle = GetWindowLong( hTaskBar, GWL_EXSTYLE );
  SetWindowLong( hTaskBar, GWL_EXSTYLE, dwStyle WS_EX_LAYERED );


  //Now, lets apply Transparency(Alpha adjustment) for our Taskbar Window.
  SetLayeredWindowAttributes( hTaskBar, 0, 200 , LWA_ALPHA );
  //Adjust the 3rd parameter to adjust transparency as you need.


Lol, liked it? Dont forget to give Feedback ;-)

PS : The method shown here is a Alpha Blending method of  just how to create a transparent Window. Transparency and Glass Efect are two different variety. You cannot create "Glass Effect" using this method. Microsoft Windows Vista/Windows7 are/may not be using this method for creating Glass effects on Windows Titlebars and Taskbar. This is a method to emulate transparency in WindowsXP/2000 only. There are various other methods to achieve real transparency, this is a basic one. Enjoy :)

Friday, July 17, 2009

Allocating a Console Window to a Win32 WIndows Application

Intro.
For some reasons or for easier Debugging you may sometimes need a console Window on a Windows Application (There is OutputDebugString() for easier debugging in Output window) But some people still love console debugging ;)


How to.

The Windows function AllocConsole() will help you to allocate a console Window with a Win32/MFC/Windows Forms Application.

Code.

AllocConsole();

freopen("conin$", "r", stdin);
freopen("conout$", "w", stdout);

cout<<"Testing :) ";

Well, the above code snippet allocates a console Window to a Win32 Windows application, and freopen() reassigns the standard input/output streams to our attached console window. Now you can use the standard Input/Output features of C/C++ like printf(), scanf(), cin, cout etc with your newly attached console window :)

PS : A process can be associated with only one console, so the AllocConsole function fails if the calling process already has a console. A process can use the FreeConsole function to detach itself from its current console, then it can call AllocConsole to create a new console or AttachConsole to attach to another console.
If the calling process creates a child process, the child inherits the new console.


-MSDN.

Friday, May 8, 2009

Add a Tray NotifyIcon in Windows - Win32 VC++


Intro.
You must have noticed in Windows versions ranging from NT/2000 onwards, an Area near the System clock display, holding some icons. This is the Taskbar Notification Area. This is also sometimes erroneously called the "tray."

And, you have seen some Applications, mainly Anti-virus applications hiding their Window from display, and running in Background with a Icon in this Notification area. Well, we call it Tray Icon too. And, what if we need to create such an icon for our Application, and hide its window from normal display?

Ofcourse you can do it. Shell_NotifyIcon() is the API which helps us to do it beautifully :) See the above picture, sorry mousepointer cannot be captured by traditional screenshot, its that Red Heart Icon representing my application displaying a tooltip given by me.

How to do.

Well. Look at the code snip given below. :)


Code Snippet.


HMENU hMenu;

NOTIFYICONDATA NID; //The Structure containing info about our Notify Icon.


BOOL Minimized = false; //A Flag.. just to indicate our Window is minimized or not


Now, add these folowing code in your Main Window's InitInstance() After the line CreateWindow().



Note : Here i have used a Resource Identifier named IDI_ICON1. Its a Resource ID. You need to Add the Icon Resource to your Resource file, and name it IDI-ICON1 or whatever you want. :)



// Size of the structure duh :)


NID.cbSize = sizeof(NID);

// The icon that will be shown in the systray.



NID.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));

// Our user defined message.(For notifications, Windows will send us messages when user pressed on our icon)



NID.uCallbackMessage = WM_USER + 1;

// Handle to the window we would like to get the notifications.



NID.hWnd = hWnd;

// Icon ID in systray...



NID.uID = WM_USER + 2;

// The tooltip string



strcpy(NID.szTip, "System Tray Icon[My App]");



// Here we say we want to get notifications about the icon, we have an icon and a tooltip.

NID.uFlags = NIF_TIP NIF_ICON NIF_MESSAGE;


hMenu = LoadMenu(hInstance, "menu1");


Now, we have the Structure filled in, and initialized. All we need to do is just Create the Icon on Tray. Wait... We dont simply need to create Icon. We need to Minimize our Application to Tray.. so, Wait for our Window to be Minimized.. What should we do then??.. Yeahh.. Capture the Window Minimizing event message. Here it is, Add to your Message handler.
case WM_SIZE:
{
if (wParam == SIZE_MINIMIZED)
{
//Set Falg to Window minimized state - true

Minimized = true;



// Hide our window just after the minimize is done.

ShowWindow(hWnd, SW_HIDE);



//Add the systray icon.

Shell_NotifyIcon(NIM_ADD, &NID);
}
}
break;
Lolzz.. its Done!.. Now, Run your code. The Window will display, Minimize it... yeah.. the Icon you proviided as IDI_ICON1 is now showing in the Notification Area.


But.. you cannot do anything with that Icon.. why?? Because we havent defined any actions to be performed on Events. Now, lets do some action with our new Notifier Icon.


I'm going to add some Menu.. yes, when the user right clicks, it should show a Menu popup(see example image below). We can use CreatePopupMenu() API to create Popup Menus.. and AppendMenu() to append Items to the Menu popuplist.


See how..


Add these following code to the end of your WndProc CallBack Function. And remember, you returns the Callback AFTER this block of code. eg : return DefWindowProc(hWnd, message, wParam, lParam);


This code comes outside of the switch(message) block and before the return DefWindowProc(hWnd, message, wParam, lParam);


//This is where we get our SysTray Icon notifications.
if (message == NID.uCallbackMessage)

{
switch(lParam)
{
case WM_RBUTTONDOWN:
{

// Create an empty popup menu
HMENU popMenu = CreatePopupMenu();


// These add items to the menu
AppendMenu(popMenu, MF_STRING, ID_MENU_SHOW, "Show");


AppendMenu(popMenu, MF_STRING, /*This should be a ID to handle the menu item*/13, "Show2");


AppendMenu(popMenu, MF_STRING, /*This should be a ID to handle the menu item*/ID_MENU_EXIT, "Exit");



// Get the position of the cursor
POINT pCursor;


GetCursorPos(&pCursor);
// Popup the menu with cursor position as the coordinates to pop it up


TrackPopupMenu(popMenu, TPM_LEFTBUTTON TPM_RIGHTALIGN, pCursor.x, pCursor.y, 0, hWnd, NULL);
}


break;


case WM_LBUTTONUP: //Did the user left click?
{ //Show the window and remove the systray icon.

ShowWindow(appWindow, SW_SHOW);

if (Minimized) ShowWindow(appWindow, SW_RESTORE);


Shell_NotifyIcon(NIM_DELETE, &NID);


}
break;
}

Well, We have now defined the Callback procedure for our Notify Icon. Now, we will get the Window Messages for our Notify Icon. We can Handle those messages from our Message Handler itself.


ID_MENU_SHOW and ID_MENU_EXIT are two Window ID's i have given to the two menu Items. You may give your own.


case WM_COMMAND:


wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);


// Parse the menu selections:
if(wmId == ID_MENU_SHOW)
{

 MessageBox(hWnd, "testing", "SysTrayIcon[My App]", MB_OK);

}
if(wmId == ID_MENU_EXIT)
{

 PostQuitMessage(0);
}
break;


Thats all... Now, you can run trhe code, and when right-clicked on the Tray Notification Icon, a Menu will popup with 3 options : Show, Show2 and Exit.


On clicking Show, it just pops up a Messagebox.. Clicking on Exit will terminate the application. You can customize the code for your need.


Sorry, if badly explained or anywhere i confused. I hope i've commented the code sufficiently and there is MSDN for your help in Documentation of API's.

I Strongly Recommend reading of MSDN for the API documentations. :)

PS : Please leave your valuable comments, and let me help improve :-)


Wednesday, May 6, 2009

How to change the "Start Menu" Text in Windows (Win32 VC++)


Intro

Windows Users must be familiar with the Start button -> the button on the lower left corner of Windows desktop placed on the Windows Taskbar. Windows versions from Windows95 to WindowsXP have a text "Start" labelled on the button. From Windows Vista onwards, this text from the Start button is discontinued.

Now for WindowsXP/2000/9x users, i'm showing a trick using the Windows API to change the Text named "Start" from the start button.
How to Do?

The Windows uses Messages to pass over informations among them. To set a text content on a Window, the Windows passes WM_SETTEXT message to the target Window. Each window are Uniquely identified using their Session Handles called HWND Handle. If we have a HWND handle of any window, we can easily send Messages and notifications to that Window using the SendMessage() API Call.

here, i need to set the text for Start Button. Since windows treats every control as a Window, the Button is also a Window. I can therefore, change the Window Text of Start button by sending WM_SETTEXT Message. But i dont have the handle of Satrt Button! There it is.. i have FindWindow() API which can easily retrive me a Handle of a Window with provided Class Name.

The classname of Taskbar, in which the Button is situated is "Shell_TrayWnd". See the Code Snippet. Its only 2 lines of Code to go. Pretty simple! :-)
Code Snippet


int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
{


  // 0x130 is the ID of StartButton
  HWND StartButton = GetDlgItem( FindWindow( "Shell_TrayWnd", NULL ), 0x130 ); 
  //Setting Start text to "Hello"
SendMessage( StartButton, WM_SETTEXT, NULL, ( LPARAM )"Hello" ); 
  return 0;
}

Thats it... Include windows.h and compile.. Cool.. huh? Dont forget to Post Feedback :-)

Thursday, July 24, 2008

Creating Transparancy in Windows using Win32 VC++

Hi all, This one, i've searched in many forums and Googled for a solution. I'm a lazy programmer.. lolz.. so, i sit in front of google for a fully cooked code for hours.. but the results were of in vein which cooked up my ass. There are a lot of codes and samples in CG Forums, CodeProject and all, but they were about Transparent window in MFC. I'm not an MFC programmer, i'm Win32 VC++ programmer, so i've no use in getting MFC codes. So, I decided to do it myself.. i just referenced MSDN and find out the way. itz nothing that Huge as you think.. just 3-4 lines of code can do it for you.. just believe me.. i'll show you how..

DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
dwStyle = dwStyle WS_EX_LAYERED;
SetWindowLong(hWnd, GWL_EXSTYLE, dwStyle);
SetLayeredWindowAttributes(hWnd, 0, 240 , LWA_ALPHA);


..can do it for you.. itz nothing.. i'll describe in brief:

1)DWORD dwStyle = GetWindowLong(hWnd, GWL_STYLE);
GetWindowLong() API is used to get the current style propery attributes of our window, where hWnd is the Window's Handle.

2)dwStyle = dwStyle WS_EX_LAYERED;
We are OR-ing the current styles of our Window with a style WS_ES_LAYERED. So that, if that styled is not applied it will get applied.

3)SetWindowLong(hWnd, GWL_EXSTYLE, dwStyle);
Nextly we are setting that Layered style to our Window using SetWindowLong() API.

4)SetLayeredWindowAttributes(hWnd, 0, 180 , LWA_ALPHA);
The Transparancy is achieved by decrementing the ALPHA values of our Window atributes. Here 180 is the Alpha value i have set for transparancy. You can decrease it for more transparancy, and increase it to make the window Opaque.

Mail me to : jithinpg007@live.com if you like the posts.. :-)