Click here to Skip to main content
Click here to Skip to main content

Window Tabifier

By , 29 Mar 2008
 
Sample Image

Contents

Introduction

This program allows to host several open Windows in one parent window so that you can easily access and navigate between them, as well as clean up space in the taskbar. The idea of creating this program came to me when I was reading an article by Jay Nelson: Hosting EXE Applications in a WinForm project. Instead of hosting just a single executable inside a WinForm project, I decided to have a tabcontrol and host different Windows on different tabs. This will allow to group similar Windows together, easily navigate between them and clean up space in the taskbar. Interested? In that case, let's start exploring the application.

Background

All the functionality of this application is achieved using Windows API functions, so you should be familiar with basic winapi programming. Consequently you should know what P/Invoke is and how it works. If you are familiar with the article: Window Tray Minimizer, then it will help you a lot.

How the Program Works

When you run the application, it hides the main form and an icon is shown in the system tray. If you right-click the icon, a context menu will be shown which has two main buttons: 'Tab Windows' and 'Tab all Windows'. When you click 'Tab Windows', a new window will pop up with a list of open Windows. The list can be filtered by the title of the Windows. When you select the Windows you wish to tabify and click 'OK', a new window will be created and all the checked Windows will be hosted in a tabcontrol. There will be one more tabpage called Menu which has two buttons: one for adding open Windows to the tabcontrol and another for choosing files that will be automatically opened in new tabs. You can also drag & drop files or folders from Windows Explorer on this tabpage for having them opened in new tabs automatically. You can navigate between tabs by clicking Ctrl+1, Ctrl+2 and so on or you can just simply hover mouse over the tab and it will be selected automatically. When selected tab changes, icon of the host window is changed either with the icon of the executable file that created current window or with the icon of the window itself. Minimizing the host window minimizes it to tray, but if it is not what you want, you can turn off the feature from the options dialog.

Code Behind the Application

Before we begin exploring the application itself, I'd like to introduce a class for storing simple properties of a window and methods for manipulation on it. The main properties are: Handle, Location, Parent, Size and Title. The main methods include closing the window, getting the path of the executable file that created the window, moving it, setting/restoring parent and setting style. There is also one static method that enumerates all open Windows. The class has one constructor that takes the window's handle as a parameter and sets its simple properties. Here is a class diagram:

WindowTabifier3.jpg

Enumerating Windows and Filtering Them

When you click the 'Tab Windows' button, a window is shown which lists all open Windows. In order to enumerate all Windows, you should call the winapi function called EnumWindows. The function takes two parameters. The first one is a pointer to a callback function. The code snippet below shows how this function works:

public static List<window> GetOpenWindows()
{
openwnd = new List<window>();

winapi.EnumWindowsProc callback = new winapi.EnumWindowsProc(EnumWindows);
winapi.EnumWindows(callback, 0);

List<window> result = new List<window>(openwnd);
openwnd.Clear();

result.RemoveAt(result.Count - 1);

return result;
}

private static bool EnumWindows(IntPtr hWnd, int lParam)
{
if (!winapi.IsWindowVisible(hWnd) || hWnd == winapi.statusbar)

return true;

openwnd.Add(new window(hWnd));

return true;
}

After this, we need to filter this list. Firstly, we need to get rid of the Windows that were opened by our application so that we don't get host Windows hosting other host Windows. This can be done for each returned window by finding the path of the executable that created the window and comparing it to our application's location. Secondly, if the user has selected to ignore Windows without a title, we have to remove them.

Finding Windows Executable

These are the steps required to find the path of the executable that created a given window:

  1. Get the process id that created the specified window using the GetWindowThreadProcessId() function
  2. Get a handle of the process by OpenProcess() function
  3. Get the executable path by calling GetModuleFileNameEx() function

All these functions are winapi functions imported by dllimport attribute. Here is the actual implementation ported to C#:

public string GetExecutablePath()
{

uint dwProcessId;

//Get the process id
winapi.GetWindowThreadProcessId(handle, out dwProcessId);

//Get the handle of the process
IntPtr hProcess = winapi.OpenProcess(winapi.ProcessAccessFlags.VMRead |
 winapi.ProcessAccessFlags.QueryInformation, false, dwProcessId);

//Get the executable path
StringBuilder path = new StringBuilder(1024);
winapi.GetModuleFileNameEx(hProcess, IntPtr.Zero, path, 1024);

winapi.CloseHandle(hProcess);

return path.ToString();
}

Filtering Windows

At this point we have a variable of List<window> class. In C# 2.0, we can use FindAll method of List<T> class to filter it.

private void GetWindows()
{
 if (Properties.Settings.Default.Ignore)
 {
 windows = window.GetOpenWindows().FindAll(delegate(window wnd) {

return wnd.Title.Length > 0 && wnd.GetExecutablePath() != Application.ExecutablePath; });
 }
 else
{
windows = window.GetOpenWindows().FindAll(delegate(window wnd) {
 return wnd.GetExecutablePath() != Application.ExecutablePath; });
 }
}

In C# 3.0, you can make use of a new feature called Lambda expressions and rewrite it like this:

private void GetWindows()
{
 if (Properties.Settings.Default.Ignore)
 {
 windows = window.GetOpenWindows().FindAll((window wnd)=>wnd.Title.Length>0 &&
 wnd.GetExecutablePath()!=Application.ExecutablePath);
 }
 else
{
windows = window.GetOpenWindows().FindAll((window wnd) => wnd.GetExecutablePath()
!= Application.ExecutablePath);
}
}

Hosting Windows

When a user selects those Windows that are to be tabbed and clicks OK, a new 'host' window is created and selected Windows are passed to it. When the host is displayed, it adds a new tabpage for each window and displays the window.

private void ProcessWindows(List<window> windows)
{
lock (tabs)
 {
 int startindex = tabs.Items.Count - 1;
 for (int i = startindex; i < windows.Count; i++)
 {
 int count = tabs.Items.Add(new FATabStripItem(windows[i].Title, null));

 windows[i].SetParent(tabs.Items[count].Handle);
 windows[i].SetStyle(winapi.GWL_STYLE, (IntPtr)winapi.WS_VISIBLE);
 windows[i].Move(tabs.Location, tabs.Size, true);
 }
 }
}

Whenever a tabpage is closed, the window that was displayed on it is released.

private void Release(window wnd)
{
wnd.RestoreParent();
wnd.SetStyle(winapi.GWL_STYLE, (IntPtr)wnd.PreviousStyle);
wnd.Move(wnd.Location, wnd.Size, true);
}

Managing Drag & Drop

Detecting drag 'n' drop of files from Windows Explorer on the menu tab is detected by the component that comes with the source code of this book: Windows Forms 2.0 Programming. When files or folders are dropped on the form or user selects them by clicking 'Open files in new tab', they are filtered and a new process is started using the filename.

private void ProcessFiles(string[] files)
{
 foreach (string filename in files)
 {
 //If it isn't a shortcut then process it.
 if (!filename.EndsWith(".lnk"))
 {
    ParameterizedThreadStart thrparam = new ParameterizedThreadStart(ProcessFile);
    Thread thr = new Thread(thrparam);
    thr.Start(filename);
 }
 }
}

The ProcessFile method starts a new process based on a parameter, waits 5 seconds for an application to become idle and then checks its MainWindowHandle property. If a folder was dropped, then it tries to get the handle to the window which was created by using winapi FindWindow function.

private void ProcessFile(object filename)
{
 string path = filename as string;
 if (File.Exists(path))
 {
 Process proc = Process.Start(path);

 if (proc != null)
 {
    proc.WaitForInputIdle(5000);
    if (proc.MainWindowHandle != IntPtr.Zero)
    {
    lock (hostedwindows)
    {
    hostedwindows.Add(new window(proc.MainWindowHandle));
    }
    }
    proc.Dispose();
 }
 }
 else
 if (Directory.Exists(path))
 {
    int i = 0;
    Process.Start(path);

    //Tries five times to find new window
    IntPtr handle = IntPtr.Zero;
    while (handle==IntPtr.Zero && i<5)
    {
    i++;
    Thread.Sleep(1000);
    // 'CabinetWClass' is the class name of explorer windows.
    handle = window.FindWindow("CabinetWClass", Path.GetFileName(path));
    }

    if (handle != IntPtr.Zero)
    {
    lock (hostedwindows)
    {
    hostedwindows.Add(new window(handle));
    }
    }
 }
}

Navigation Between Tabs

Except just clicking the tab with mouse which you wish to select there are two ways to navigate between them: You can either click Ctrl+1, Ctrl+2, etc. at the same time to switch to the corresponding tab or you can simply hover mouse over the tab and it will be selected automatically. The code snippets below show how these are accomplished.

Code Snippet for Ctrl+1, Ctrl+2, etc.


private void tabs_KeyDown(object sender, KeyEventArgs e)
{
 //Check if Ctrl key is pressed and that there is
 //corresponding tab item to the number which was pressed.
 if (e.Control && e.KeyValue>48 && e.KeyValue<58 && tabs.Items.Count>=(e.KeyValue-48))
 {
 tabs.SelectedItem = tabs.Items[e.KeyValue - 49];
 }br>}

Code Snippet for Automatically Selecting Tab when Mouse is Moved Over It


private void tabs_MouseMove(object sender, MouseEventArgs e)
{
 //Make sure that there is tab under mouse and that automatic selection is enabled.
 FATabStripItem c = tabs.GetTabItemByPoint(e.Location);
 if (c != null && Properties.Settings.Default.SelectonHover)
 {
 tabs.SelectedItem = tabs.Items[tabs.Items.IndexOf(c)];
 }
}

Host Window Icon

When you change active tab in host window, the host window icon changes either with the icon of the executable file that created the currently displayed window or with the icon of the window itself that is displayed. So we need to retrieve either the executable icon or the window's icon.

Retrieving Executable Icon

In order to retrieve the executable icon we need to call SHGetFileInfo() and pass the path of the executable file and an instance of SHFILEINFO structure. After you have retrieved a handle to the icon, you must call DestoyIcon() API to prevent a memory leak.

private Icon GetIcon()
{
 System.Drawing.Icon icon = null;
 string path = GetExecutablePath();

 if (System.IO.File.Exists(path))
 {
    //Retrieve SHFILEINFO type variable
    winapi.SHFILEINFO info = new winapi.SHFILEINFO();
    winapi.SHGetFileInfo(path, 0, ref info, (uint)Marshal.SizeOf(info),
            winapi.SHGFI_ICON | winapi.SHGFI_SMALLICON);

    //Create icon and destroy the handle
    System.Drawing.Icon temp = System.Drawing.Icon.FromHandle(info.hIcon);
    icon = (System.Drawing.Icon)temp.Clone();
    winapi.DestroyIcon(temp.Handle);
 }

 return icon;
}

Retrieving Window Icon

In order to retrieve window icon, I used the code snippet from this article: Screen Captures, Window Captures and Window Icon Captures with Spy++ Style Window Finder! with small modifications. Here it is:

private Icon GetWindowIcon()
{
 int result;

 winapi.SendMessageTimeout(handle, winapi.WM_GETICON, winapi.ICON_SMALL, 0,
 winapi.SMTO_ABORTIFHUNG, 1000, out result);

 IntPtr IconHandle = new IntPtr(result);

 if (IconHandle == IntPtr.Zero)
 {
 result = winapi.GetClassLong(handle, winapi.GCL_HICONSM);
 IconHandle = new IntPtr(result);
 }

 if (IconHandle == IntPtr.Zero)
 {
 winapi.SendMessageTimeout(handle, winapi.WM_QUERYDRAGICON, 0, 0,
 winapi.SMTO_ABORTIFHUNG, 1000, out result);
 IconHandle = new IntPtr(result);
 }

 if (IconHandle == IntPtr.Zero)
 {
 return null;
 }

 System.Drawing.Icon temp = System.Drawing.Icon.FromHandle(IconHandle);
 System.Drawing.Icon icon = (System.Drawing.Icon)temp.Clone();

 winapi.DestroyIcon(IconHandle);

 return icon;
}

Managing Start-up

You can add the program to start-up from the options Window. To add program to start-up, you need to navigate to HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run key, create a new string and set its value equal to the application's path. Removing the program from start-up is easier: you just remove the value. The code snippet below shows how to do it:

[RegistryPermissionAttribute(SecurityAction.LinkDemand,
 Write = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run")]
private void startup(bool add)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\
 CurrentVersion\Run", true);

if (add)
{
key.SetValue("Window Tabifier", "\"" + Application.ExecutablePath + "\"");
}
else
key.DeleteValue("Window Tabifier");

key.Close();
}

Making the Application Single-instance

If you try to launch the second instance of the application, you will get a message box saying that it is already running. This is achieved using the mutex class. Mutex allows to share resources between threads. When the first instance of the program is launched, it creates a new mutex. When a second instance is launched, it checks the existence of the mutex. If it exists, then it exits. When the first instance quits, it releases the existing mutex.

static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Mutex mt = null;

try
{
//Try to open existing mutex
mt = Mutex.OpenExisting("Window Tabifier");
 }
 catch (WaitHandleCannotBeOpenedException)
 {

 }

 if (mt == null)
 {
 //If the mutex doesn't exist create it and launch the application.
mt = new Mutex(true, "Window Tabifier");
 Application.Run(new Main());

 //Tell GC not to destroy mutex until the application is running and
//release the mutex when application exits.
GC.KeepAlive(mt);
mt.ReleaseMutex();
}
else
{
//The mutex exists so exit
mt.Close();
MessageBox.Show("Application already running");
 Application.Exit();
 }
}

Possible Enhancements

These are possible features that would make the application more useful:

  • Detecting window opening automatically and adding it to the host window
  • Detecting WM_SETTEXT message for tabbed Windows in order to update tab title.

Both features require setting Windows hooks.

Points of Interest

While experimenting with this application, I found that if you start a new process through file shortcut, then the return value is always null.

References

I would like to thank Giorgi Moniava for the advice he gave me.

History

  • 20th January, 2008 - Initial release

  • 11th February, 2008 - version 1.5

    Bugs Fixed

    • Bug #1: When a tabbed window is released, it has the same state as before it was tabbed. (If the window was maximized before tabbing, it will be maximized after it is released.)
    • Bug #2: When a minimized window is released, you no more need to right-click it with the mouse and click restore in order to open it, you can just click it with the mouse as you usually would.

    Features Added

    • Feature #1: You can now drag and drop a folder on the host window and it will be automatically opened in a new tab.
  • 6th March, 2008 - version 1.6

    Features Added

    • Feature #1: A tab is selected automatically when the mouse is moved over it.
  • 20th March, 2008 - version 1.8

    Features Added

    • Feature #1: When you change the active tab in the host window, the host window icon is set to the icon of the executable file that created the currently displayed window.
    • Feature #2: Host window minimizes to system tray. This feature can be turned off from the options dialog.
  • 29th March, 2008 - version 1.9

    Features Added

    • Feature #1: When you change the active tab in the host window, the host window icon changes either with the icon of the executable file that created the currently displayed window or with the icon of the window itself. This behaviour can be configured from the options dialog.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Giorgi Dalakishvili
Software Developer
Georgia Georgia
No Biography provided
Follow on   Google+

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionProblem in using this code.memberMahesh Murty13-Oct-12 0:51 
Hi Everybody,
I tried to use the code of this application in my project. I wanted to run an application whose path is known to me into my form. So I wrote this code on button click in my application:-
 
private void button1_Click(object sender, EventArgs e)
       {
           Process P = Process.Start(@"C:\Program Files (x86)\Angry Birds\Angry Birds 1.0\AngryBirds.exe");
 
           lock (P)
           {
 
               window wind = new window(P.Handle);
               wind.SetParent(groupBox1.Handle);
               wind.SetStyle(winapi.GWL_STYLE, (IntPtr)winapi.WS_VISIBLE);
               wind.Move(groupBox1.Location, groupBox1.Size, true);
           }
 
           
 
       }
But it is not working. What is wrong? Can you please point it out?
QuestionNice workmemberghvnd10-Sep-12 1:17 
Very good work. Small and efficient.
GeneralMy vote of 5memberghvnd10-Sep-12 1:13 
totally awesome!!!
Very good work Smile | :)
Questionhow to embedd the popps also in the windowmemberdeveoper1234521-Oct-11 2:52 
Hi it is a cool application I really like it.But sometimes I got the requirements like also dock all generated popups from third party exe in my application. Is it possible?
Can you suggest some code?
 
Thanks
GeneralMy vote of 5memberIndivara25-Nov-10 16:25 
Great work, and really useful tool!
 
If you consider updating this, try it out with Vista's Windows Explorer. The non-standard frame is visible through the tabs (it works, just looks a little strange)
 
-- update --
After using this for sometime, it really rocks! You know how hard Vista's explorer is to use? Well this makes it bearable by allowing several instances to be tabbed (like QTtabBar, but much lighter and no shell extension needed)
 
You really should consider distributing this more actively.
 
Thumbs Up | :thumbsup:
GeneralcoolmemberMember 30146966-Sep-10 21:58 
this is so cool, i bow before you Smile | :)
thanx for this tutorial, has helped a lot
QuestionSingle process can hang all other processesmemberblahblah996-Aug-10 6:43 
Hi Giorgi. Thanks for the great project you've started.
 
I have found a bug that I can't seem to resolve that occurs when one of the tabbed processes hangs/sleeps, then the other tabs become inaccessible when clicking on them. Hover (mouse-over) still works to change tabs, but if you disable the hover option, clicking on the other tabs does not fire the change tab event until the process that is hung/sleeping finishes processing.
 
Problem: When one tabbed processes hangs/sleeps, the mouse clicking on another tab will hang the whole tabifier window until the hang/sleep is finished.
 
Steps to recreate:
1. Create a simple EXE/GUI with a button that calls System.Threading.Thread.Sleep(10000);
2. Start two instances of this EXE
3. Start Window Tabifier
4. Disable mouse-over tab switching in Window Tabifier
5. Add the two instances of the sleeper EXE as tabs
6. Click the button in one of the instances that sleeps for 10 seconds
7. IMMEDIATELY try to switch to a different tab: This does not switch until the 10 seconds are up.
 
Why this is a problem: A process that freezes will not allow me to access any other tabbed processes, and any work I am doing in them may not be saved, etc, etc...
 
Notes:
-This problem only occurs on some systems. I use Windows XP SP3, and have run my release & debug mode EXEs and this problem occurs on only some machines. On others, it switches tabs fine (my dev machine with VS 2008, this works fine.
-I am using VS 2008, have tried .NET 2.0 and 3.5, in release a debug modes.
GeneralNice application! CongratulationsmemberWojciech28-Apr-09 8:32 
I like it very much, and start some experiments with it. Is it possible to publish such programs with your name as author and links to this article?
 
Also can You help me with one problem?
How to take WindowTabifier to top, when hosted application is focused?
 
great work
GeneralRe: Nice application! CongratulationsmvpGiorgi Dalakishvili28-Apr-09 8:35 
Yes, you can post it if you also indicate that is was developed by me and link to this article.
 
Can you make your second question clearer?
 

GeneralRe: Nice application! CongratulationsmemberWojciech28-Apr-09 8:52 
I modified Your application as prototype of my idea of light IDE: http://intype.info/forums/discussion/831/intype-commander-icmd-20-/[^]
 
When I want to get to hosted Firefox (click on hosted window) from external application WindowTabifier don't go to the top, so I need to minimalize all other windows or focus Window Tabifier.
 
Is it possible to catch hosted firefox focus, to bring Tabifier to the top?
QuestionPls help for FarsiLibrarymembermightygirls16-Apr-09 23:06 
This Article is very nice and helpfull. Can you pls. tell me from where i'll get
that Tabstrip.dll's code and DragAndDropFileComponent.dll's source code... I would
like to see the full code... because am not much expert in .NET.
Thanks in Advance.
 
Jiby

AnswerRe: Pls help for FarsiLibrarymvpGiorgi Dalakishvili18-Apr-09 5:28 
Here you are:
TabStrips: A TabControl in the Visual Studio 2005 way![^]
 
2nd edition book sample code for Visual Studio 2005 and the .NET Framework 2.0 in C#[^]
 

Generaldamn awesomemember Xmen 20-Mar-09 4:20 
thanks man for sharing your hardwork...
 


TVMU^P[[IGIOQHG^JSH`A#@`RFJ\c^JPL>;"[,*/|+&WLEZGc`AFXc!L
%^]*IRXD#@GKCQ`R\^SF_WcHbORY87֦ʻ6ϣN8ȤBcRAV\Z^&SU~%CSWQ@#2
W_AD`EPABIKRDFVS)EVLQK)JKQUFK[M`UKs*$GwU#QDXBER@CBN%
R0~53%eYrd8mt^7Z6]iTF+(EWfJ9zaK-i’TV.C\y<pŠjxsg-b$f4ia>
-----------------------------------------------
128 bit encrypted signature, crack if you can

GeneralRe: damn awesomemvpGiorgi Dalakishvili20-Mar-09 6:25 
Xmen wrote:
thanks man for sharing your hardwork...

 
You are welcome. I have some more plans about it to make it more robust. I hope I'll find time for it Smile | :)
 

GeneralRe: damn awesomemember Xmen 20-Mar-09 6:28 
cool Big Grin | :-D
 


TVMU^P[[IGIOQHG^JSH`A#@`RFJ\c^JPL>;"[,*/|+&WLEZGc`AFXc!L
%^]*IRXD#@GKCQ`R\^SF_WcHbORY87֦ʻ6ϣN8ȤBcRAV\Z^&SU~%CSWQ@#2
W_AD`EPABIKRDFVS)EVLQK)JKQUFK[M`UKs*$GwU#QDXBER@CBN%
R0~53%eYrd8mt^7Z6]iTF+(EWfJ9zaK-i’TV.C\y<pŠjxsg-b$f4ia>
-----------------------------------------------
128 bit encrypted signature, crack if you can

GeneralThis app rulesmemberVodstok24-Dec-08 4:24 
I just felt the need to publicly aknowledge how much help this app has been for me. I am currently working in an environment that uses windows XP and office 2003. I am used to office 2007 in vista, so "minimize outlook to tray" is a standby to me. Thanks to this, i get the same functionality.
 
Additionally, I am able to run multiple IE windows without cluttering up my workspace, and was just able to integrate the "window grab" into a testing app for Watir.
 

Thanks to Giorgi for introducing me to this.
 
______________________
Oh Hamburgers!

GeneralRe: This app rulesmvpGiorgi Dalakishvili24-Dec-08 7:44 
Thank you very much for your comment Smile | :)
 
Any ideas for improving it?
 

GeneralRe: This app rulesmemberVodstok24-Dec-08 8:58 
A small one. Adding an event for the tab control to handle resize event, and reusing .Move(new Point(0, 0), tabber.Items[0].Size, true);
 
resizes the tabbed windows nicely. you have to loop through the windows and assign it to each one.
this is what i am using
tabs.Resize += new System.EventHandler(tabs_Resize);
 
the above goes in the Host.Designer.cs
 
and this goes in Host.cs
 
private void tabs_Resize(object sender, System.EventArgs e)
{
foreach (window w in hostedwindows)
{
w.Move(new Point(0, 0), tabs.Items[0].Size, true);
}
}
 
______________________
Oh Hamburgers!

GeneralRe: This app rulesmvpGiorgi Dalakishvili23-Nov-09 1:57 
Hi,
 
Have you added the code you suggested? Is it working well?
 
Thank you.
 

GeneralMy vote of 1memberProJester12-Dec-08 10:43 
dangerous
GeneralRe: My vote of 1mvpGiorgi Dalakishvili8-Dec-08 2:39 
That's all you have to say? No reason no explanation?
 

GeneralRe: My vote of 1memberDan Letecky15-Dec-08 23:36 
Don't worry, Georgi. It's a nice article. You got 5 from me.
 
--
My open-source ASP.NET 2.0 controls:
DayPilot - Outlook-like calendar/scheduling control
DayPilot MonthPicker - Light-weight month picker
MenuPilot - Hover context menu

GeneralRe: My vote of 1mvpGiorgi Dalakishvili16-Dec-08 1:11 
Thank you Dan Smile | :)
 

GeneralSuggestions & ideasmemberMarcus Deecke7-Nov-08 23:12 
Hi
 
Nice project, first of all.
 
When I was searching for projects like yours my intention was to organize my Windows Explorer windows.
Therefore your Possible Enhancement of detecting the WM_SETTEXT message is vital.
When the the selected directory in a Explorer window changes and the caption will not be updated, how to navigate?
 
Your first enhancement of detetcting opening windows would be nice, as well. The idea could be to centralize all windows of certain applications in a Tabifier host window.
E.g. all Explorer windows are combined in one Tabifier instance and all console windows are combined in another. This should be customizable.
 
Some goodies would be bookmarks and something like projects, which make it possible to group windows to reopenable projects.
 
I think your project has the potential for a real good and useful app. If continued.
 
Regards
Marcus
GeneralRe: Suggestions & ideasmvpGiorgi Dalakishvili8-Nov-08 3:48 
Hi,
 

Marcus Deecke wrote:
Nice project, first of all.

 
Thanks. It really makes me feel better when I know that someone liked what I did Smile | :) Thanks for the interesting comments too.
 
Marcus Deecke wrote:
Therefore your Possible Enhancement of detecting the WM_SETTEXT message is vital.
When the the selected directory in a Explorer window changes and the caption will not be updated, how to navigate?
 
Your first enhancement of detecting opening windows would be nice, as well.

 
Unfortunately it's quite difficult if not impossible to use global hooks from c#
 
Marcus Deecke wrote:
The idea could be to centralize all windows of certain applications in a Tabifier host window.

It's an interesting idea. However, people usually don't have many instances of same application open so the application might lost its idea if the taskbar is still full of windows. But having an option is possible.
 
I think it would be better to organize windows from same application in tabs next to each other. E.g. first all tabs from windows of explorer, than all tabs from firefox and so on. This should be customizable as well.
 
The best option would be to have the ability to reorder tabs at runtime. Ideally, I am looking for a tabcontrol that supports runtime reordering of tabs, icons for each tab (both exist in firefox) and close button (like in this application). One possible way of tab reordering is to show a window that lists all open tabs and allows user to reorder them there and will automatically apply it to existing tabs.
 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130619.1 | Last Updated 29 Mar 2008
Article Copyright 2008 by Giorgi Dalakishvili
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid