July 31st, 2010 5:50:54 pm pst by
Sterling Camden
Now that I’ve been using XMonad as my window manager on FreeBSD for a while, I find that when I have to work on Windows one of the more painful aspects thereof is, ironically, window management. I spend way too much time hunting for the right window or arranging windows so I can clearly see all the ones I need at once. Windows Vista and 7 have the ability to view windows side-by-side or stacked, but that’s not adequate to my needs and it virtually requires using the mouse. I desperately want an automatic tiling window manager like XMonad.
So, I created the next best thing: a command-line utility that will arrange all the windows in a tiled fashion, according to a pattern specified per monitor. In the download below you will find all the sources, plus in the Release subdirectory I’ve included an executable built with Visual Studio 2010.
For usage, type ’tile’ at a command prompt without arguments. But, to give you some examples:
tile 1 2
This tiles both the primary and second monitors using a column-based scheme, with no maximum of columns. Each display will be divided into the number of columns needed to hold all of the windows on that monitor.
tile 1:2r 2:3c
This tiles the primary monitor into 2 rows, with each row split as evenly as possible to accomodate all of the windows. Thus, if the primary window contains three windows, the first window will occupy the entire top row, and the second row will be split between the other two windows. On monitor #2, we’ll have three columns — so if we have five windows there, we’ll get one window in the first column and two windows stacked in each of the two remaining columns.
If you specify more rows or columns than there are windows on that monitor, it’s automatically reduced to the number of windows. Tile silently ignores most errors, such as specifying a monitor that doesn’t exist. Tile does not affect windows that are maximized or minimized. In order to be considered within a monitor, at least 10 pixels of the window in both directions must intersect the monitor’s rectangle.
As noted above, all parts of an argument except for the monitor number are optional. If omitted, the max defaults to 99, and row/column defaults to column.
So, now I can choose my optimal layout, put it in a little batch file named ‘t.bat’, and whenever I need my windows to snap into place I can just type ‘t’ at a command prompt.
Posted in C and C++, Wildly popular, Windows |
1 Comment » RSS 2.0 | Sphere it!
January 28th, 2010 11:05:37 am pst by
Sterling Camden
A commenter going by Anonymous Coward (I bet that’s not his real name, and I beg forgiveness if the masculine pronoun doesn’t apply) provided a solution to the double-spaced output problem users occasionally experienced with my tee utility for Windows.
Naturally, this issue occurred because of the inconsistent usage of carriage-returns and linefeeds to terminate lines of text, combined with Console::ReadLine’s interpretation thereof. The solution, simply enough, was to use BinaryReader for input, and BinaryWriter for output, so no interpretation or translation of the characters would occur.
Like most good programmers, once he had inserted hands in the code, Anonymous Coward couldn’t leave this one alone. He coded up several more features and emailed them to me. I made a few corrections and included the new version here.
New features include:
- Duplicated file names are silently ignored, rather than causing a file open conflict.
- /? or –help displays usage information.
- -i or –ignore ignores cancel (Ctrl+C), instead of always ignoring it.
- -f optionally marks the end of switches and interprets all remaining arguments as filenames.
Thanks, Anonymous Coward – whoever you are!
Posted in .NET, C and C++, Windows |
1 Comment » RSS 2.0 | Sphere it!
June 28th, 2008 1:37:07 pm pst by
Sterling Camden
I often check my referrer logs to see how people found my site. Chip’s Tips gets the vast majority of its traffic from search engines. Sometimes I’ll see a search that didn’t quite reach its intended result, and that will inspire a new post.
Quite often I see “ruby tee windows” or something similar, which leads people to my tee utility for Windows. That seems fair enough, except that it isn’t written in Ruby. It’s written in C#, which means that it has 12 source files and the “real” code requires 29 lines. Furthermore, since it’s a .NET executable, it won’t run if it’s installed in a folder that isn’t “trusted”. Talk about red tape.
Besides, this application is trivial with a capital TRIV in Ruby, using the ‘shell’ library. Heedless of its impact on page load time, I’m including the entire source file right here:
require 'shell'
Shell.new.tee(ARGV[0]) < STDIN > STDOUT
Save that to tee.rb, and then you can perform the canonical basic test:
echo hello world | tee.rb "hello.txt"
See “hello” echoed to the console, and check out the contents of hello.txt. Naturally, this utility is far more useful for trapping the log of a long build procedure or some other process that generates tons of output, but which you’d like to see echoed to the console at the same time.
Of course, you could also do the whole thing at the command line:
echo hello | ruby -e "require 'shell';Shell.new.tee('hello.txt') < STDIN > STDOUT"
But I like having it saved in a file so I don’t have to remember it. This should also work just fine on *nix systems, but heck you’ve got the native tee there.
Posted in Ruby, Unix, Windows |
9 Comments » RSS 2.0 | Sphere it!
May 5th, 2008 11:23:28 am pst by
Sterling Camden
On Windows, Synergy/DE provides access to the mouse cursor via the WP_CURSOR subfunction of W_PROC. Because this API is purely imperative, managing a wait cursor properly becomes a recurring problem in non-trivial applications. Typically, it begins like this (in pseudo-code):
set wait cursor
do lengthy process
clear wait cursor
But what happens if “do lengthy process” throws an exception that’s caught outside this code? You’ll skip right over “clear wait cursor” and leave the user unable to click anything. What you’d like to do is more like this:
begin
set wait cursor
do lengthy process
end
… and have the cursor reset whenever and however you exit the code block.
The downloadable code below demonstrates how to do this with the new object syntax in Synergy/DE version 9. The WaitCursor class sets the wait cursor in its constructor and resets it in its destructor. So you can code it like this:
begin
data wait, @*, new WaitCursor()
do lengthy process
end
The data statement declares a variable that has the scope of its containing begin-end block. The variable wait is declared as an object (@*). We could have more precisely declared it as @WaitCursor, but that’s just more typing (pun intended). It’s initial value is returned by the “new” expression, creating a new WaitCursor object. This invokes its constructor, setting the wait cursor. When wait goes out of scope, the last reference to the object is lost, and the destructor is invoked and the cursor is reset — no matter how you get out of the code block. If you want to preserve the cursor instead, you can just pass a reference to the object out of the block in another variable, and clear that variable when you no longer want the wait cursor.
But what happens if you have nested operations that, agnostic of each other, each want to set a wait cursor? When the inner one finishes, it will reset the cursor to normal. That’s not what you want at all. I solved this by adding a static counter to the class, so we only reset the cursor if our count of active WaitCursor objects gets back to zero.
Of course it’s possible that other code is manipulating the cursor without using our class. That could definitely interfere with our scheme, and should be avoided if possible. One common case is the set of message box routines in the UI Toolkit (U_MESSAGE, U_MSGBOX, U_WAIT). These routines always reset the cursor to the normal pointer so the user can use the mouse to click the buttons. If you want to have the cursor go back to what it was before these routines were called, then you’ll probably need to wrap them in your own version that saves off the current cursor state, calls the original, and then restores the cursor.

Posted in SynergyDE, UI Toolkit, Windows |
2 Comments » RSS 2.0 | Sphere it!
February 29th, 2008 1:51:12 pm pst by
Sterling Camden
As an independent consultant who bills by the hour, I have to keep track of how much time I spend on projects for different clients. When various emergencies arise, that can get pretty confusing to reconstruct at the end of the day. I needed an easy way to monitor my time with just a few mouse clicks. So a few years ago I created the simple stopwatch application that you can download below. One click to start, another to stop. You can enter a description, and previously entered descriptions are remembered in a dropdown. You can run multiple instances to keep track of time for multiple clients. At the end of the day, you’ve got a total for each.
I wrote this as a C# Windows application using Visual Studio 2003. Converting it for VS 2005 introduced a challenge, because accessing a control from another thread (the timer’s) is now considered unsafe and throws an exception. So as you’ll see in the SetText method, I adopted a work-around from the MSDN documentation.
Back when I wrote this application, the code seemed quite concise. Now that I’m older and wiser and have been exposed to Ruby, I can’t get over how verbose it is. I can’t help but think that to do the same thing in JavaScript would be pretty trivial. Maybe I’ll give it a go one day.

UPDATE 11/10/2008: Here’s the JavaScript version.
Posted in .NET, C#, Wildly popular, Windows |
15 Comments » RSS 2.0 | Sphere it!
March 18th, 2007 1:23:32 pm pst by
Sterling Camden
Working remotely via VPN on a big project presents some challenges, not the least of which is keeping your local source files up to date with the thousands of version control archives. Running a script to check all of the remote archives against your local sources can take a lot of time and bandwidth. Yet, if you don’t stay up to date, how will you know if your changes will be compatible with the latest version? You’d really like to know exactly which archives have been modified and just check those against your local copies.
One such project I work on uses PVCS for version control. PVCS writes a log file for all modifications to the archives. Each entry in the log contains the name of the archive file (full path), the person who made the modification, the date, time, and nature of the modification — all comma-delimited. So, I wrote a handy little Ruby script (which you can download below) to read the log, looking for updates on or after a specified date. For those it finds, it spawns a PVCS ‘get’ command using -u (update only if more recent) and -n (answer ‘n’ to any prompts, such as “a writable version exists, overwrite?”).
Even if you don’t have a need for such a script yourself, you might find some interesting features of Ruby in this example. Or, if you’re a better Rubyist than I, maybe you could show me how to make this script even more elegant.
The archives are stored in a directory structure that mirrors the source file directory structure on the local machine. Development occurs on both *nix and Windows workstations, so the root of the archive path in the log may be ‘/usr/archive’ or a drive letter mapped over Samba. Thus, we must strip off any of these archive path prefixes, and then add our local source root, in order to know where each source file needs to go.
To avoid duplication of effort, we use a hash keyed on the full archive path (with root prefix stripped). The corresponding value in the hash is an array containing the archive directory and the filename.
See the comments within the script for further information and usage instructions.
Posted in Ruby, Unix, Wildly popular, Windows |
1 Comment » RSS 2.0 | Sphere it!
January 24th, 2007 1:14:10 pm pst by
Sterling Camden
Quite frequently, sometimes several times a day, a Google search for something like “launch application by file extension” or “shellexecute” will bring the errant searcher to this post, which describes how to do just exactly that — in Synergy/DE. Unfortunately, most of these seekers of wisdom usually add “C#” or “ruby” to their queries.
I hate to see people land on my site and not get the answer they’re looking for. So lets give them something to find, shall we?
No need to create a C# example because there’s a great one over on The Code Project.
However, a good Ruby example eluded my search, so I whipped one up. You can download it below. As you might expect, it creates a Win32API object for the necessary linkage to ShellExecute in shell32.dll, then calls it to launch the associated application for whatever file and verb you pass. Naturally, this only works on Microsoft Windows platforms.
Posted in C#, Ruby, Wildly popular, Windows |
8 Comments » RSS 2.0 | Sphere it!
August 1st, 2006 9:31:11 am pst by
Sterling Camden
On Windows platforms, Synergy/DE lists provide three different ways to handle a mouse double-click:
- By default, a RETURN is simulated (thus selecting the item, when using L_SELECT).
- You can register a list double-click method in the listclass, or by using L_METHOD with D_LDBLCLK.
- You can include a UWNDEVENTS_METHOD for double-click in a method set provided to L_METHOD with D_LWNDEVENT.
But what if you just want to suppress any action on double-click? The downloadable code below shows you how. The example includes a subroutine to modify the style of the window class to disable or enable double-clicks. Note, however, that because this style is included in the window class rather than the window itself, the change affects ALL Listbox windows in the entire application (thanks, Microsoft). So, a good practice is to change the style for the smallest possible duration, and then change it back.
Note also that this technique does not work with the ActiveX list, although a similar technique could be used (hint: the Spread window is a grandchild of the container, and its class name changes with each major version). UPDATE: I modified this code to work for ActiveX lists as well (just for you, Glynis). Note that on the next major version of Spread, the class name used (“SPR32A70_SpreadSheet”) will no doubt change. Also, when you call this routine for an ActiveX list, the double-click suppression will apply to not only all ActiveX lists in your application, but also to any Spread controls you may be using.
The example also includes code that requires Synergy/DE version 8.3 or higher.
Posted in SynergyDE, Wildly popular, Windows |
1 Comment » RSS 2.0 | Sphere it!
April 12th, 2006 4:15:41 pm pst by
Sterling Camden
Thanks to Steven Parrish of BusinessCraft Pty Ltd in Australia for this one.
When bridging between Synergy/DE and .NET components, you would usually choose to create a .NET component that invokes Synergy/DE code on the back-end using xfNetLink.NET and xfServerPlus. Another approach is to access the SynergyDBMS directly from .NET code using xfODBC. You can also call .NET components from Synergy/DE code on the back-end using web services. But, if you would like to have your client application written in Synergy/DE using .NET windows forms, you were out of luck — until now.
Synergy/DE on Windows has an ActiveX interface, but no direct .NET interface (yet). The good folks at Synergex are planning to create a CLR version of Synergy that would allow you to mix and match Synergy code with C#, VB.NET, and any other CLR language, but that won’t be available for a while (version 10 is the current plan).
You can create a COM component in .NET by registering a type library for the assembly, which has to be strong named and loaded in the GAC. However, that doesn’t make it available to the Synergy ActiveX interface, because it isn’t an ActiveX control. So, one more bridge is needed: create an ActiveX control that automates the .NET/COM component, and pass through the methods, properties and events.
The download below is exactly in the form in which Steven gave it to me. It’s a proof-of-concept comprised of three main parts:
SynergyInterop: a solution written in Visual Basic .NET, which includes the COM Interop component and a sample form
GatewayVB6: a Visual Basic 6.0 ActiveX control to bridge between Synergy and the COM Interop component
DBL: A directory containing Synergy/DE test harness code and a SynergyDBMS database
The main directory also has two batch files for registering the type library and loading the assembly into the GAC.
The sample application passes through one method call, “ShowForm”, to display the windows form, and two events:
ReadRecord – retrieve a record from the database
SendMessage – send various information back to the host application
When I have more time I would like to explore the possibilities for generalizing this approach. It seems to me that you could use a PlugIn interface to load various forms or other .NET components into the Interop layer, and then use reflection to access methods, properties and events by name at runtime. Whether or not I will find the time to do that before Synergy v10 is released, who can say?
Blogged here
UPDATE: Synergy/DE version 9 includes a new API for embedding .NET components in non-.NET Synergy applications on Windows. The interface was partially inspired by this post, which in turn was inspired by Steven Parrish’s work. Thanks again, Steven!
Posted in .NET, ActiveX, SynergyDE, Visual Basic |
No Comments » RSS 2.0 | Sphere it!
April 5th, 2006 2:46:23 pm pst by
Sterling Camden
In Synergy/DE on Windows, the colors applied to some parts of your application are determined by the Windows registry, rather than by renditions settings in Synergy/DE. This means that most of the time a user can figure out how to control a given component’s rendition by looking in Windows Control Panel or the Synergy Control Panel.
Not so for disabled fields. Windows does not provide a visual means for altering the “gray text” rendition, and it forces that rendition on all disabled fields. There is literally no way around it, short of subclassing the display for edit controls. With the default background color being a darker gray, the text of disabled fields can be difficult to read, which has caused some frustration for Synergy/DE users and developers.
All Windows colors can be programmatically manipulated via the user32.dll function “SetSysColors”. The download below demonstrates how to modify the COLOR_GRAYTEXT system color to whatever color you would like. Note, however, that after you change that color, the change takes effect for ALL applications from this point forward for the current user. So, wield this weapon with care.
Blogged about this here.
Posted in SynergyDE, UI Toolkit, Wildly popular, Windows |
2 Comments » RSS 2.0 | Sphere it!
March 15th, 2006 5:31:35 pm pst by
Sterling Camden
Ah, the wonderful world of colors…so many ways to define them. In the Synergy/DE world, a color palette is defined as a set of 16 foreground/background combinations (yes, this seems a little restricted, but it was designed back in the days when it made a difference that the zero-based index could be stored in 4 bits). The foreground and background colors are defined as color codes from 0 to 255, just to create more numeric confusion. These codes are platform-specific, but on Windows platforms they are each defined as an RGB (red-green-blue) triplet. You can define them, as well as the palette entries, in the synergy.ini file in the [COLORS] section. You can also change them at runtime, using the %U_WINCOLOR UI Toolkit function with the D_SETCOLOR subfunction.
Thus our bridge from Windows colors to Synergy/DE colors. Windows system colors can be retrieved as RGB triplets using the Win32 API function “GetSysColor”. The downloadable code below provides a function that will set a Synergy color (0-255) to one of the Windows system colors. The included example then shows how to assign the newly formed color to a Synergy/DE Toolkit rendition.
Hey, at least we don’t have to worry about hue, luminosity, and saturation.
News flash! Synergy/DE version 8.3 (and later) includes built-in support for Windows system colors as color values above 255.
Posted in SynergyDE, UI Toolkit, Windows |
No Comments » RSS 2.0 | Sphere it!
January 25th, 2006 4:03:47 pm pst by
Sterling Camden
The ActiveX list provided in Synergy/DE includes a number of published methods that take the list column number as an argument. The column number does not directly map to the number of fields and/or prompts, because prompts only get a column if the field is not a checkbox. Thus, a bit of logic is required to programmatically determine the column number for a specific field.
The download below includes a function, %get_listfldcol, to which you pass the ID of the list and either the name or the number of a Toolkit field within the associated input window. The function returns the ActiveX list column number for the “field” portion of the field (i.e., not the prompt), or zero if the field is not found in the window.
Posted in ActiveX, SynergyDE, UI Toolkit, Windows |
No Comments » RSS 2.0 | Sphere it!
November 11th, 2005 4:40:08 pm pst by
Sterling Camden
Windows associates applications with operations on files having specific extensions. While this notion can be annoying (mostly due to collisions), it can also be useful. Users can customize associations to launch whatever application they feel most comfortable using to manipulate a specific type of document.
Synergy applications can make use of those associations via the ShellExecute API. The downloadable example code below illustrates how to use this routine to launch a document with the file extension “.xls” using whatever application is registered to handle the “open” operation on that file extension (e.g., Microsoft Excel).
For full documentation of the ShellExecute function, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shellexecute.asp
The example also addresses a common problem in Synergy with launching external applications. Synergy often steals the activation and/or focus from the launched application when the Synergy application re-enters an input routine (e.g., the UI Toolkit routine I_INPUT).
Activation is a tricky thing in Windows, and differs between Windows versions. Before Windows 98, if an application activated itself, well, it was activated. Then the Active Desktop imposed a new rule: only the foreground application (or the user) can activate an application. An application that tries unsuccessfully to activate itself is now relegated to flashing its taskbar window in protest. When ShellExecute launches an application, Windows acts like the user launched it and brings it to the front. BUT, if the Synergy application activates itself in time (before the launched application gets a chance to get on its feet), then the Synergy application will stay on top.
Thus, to insure that the launched application comes out on top, the example contains a subroutine named activate_and_wait. You can pass this routine the window class and/or caption of the application to activate. Whether or not that application can be found, the routine then waits for the Synergy application to be reactivated by the user (either by clicking on it, Alt-Tab, or some other means — or after the launched application is closed) before returning. This puts the onus on the user to say when Synergy should become reactivated. The routine uses an ActiveX control (ActivationX.ocx) to accomplish this. For the sources to the control (written in C++ using MFC) and documentation of its properties, methods, and events, see ActiveX monitor for window messages.
Posted in ActiveX, SynergyDE, Wildly popular, Windows |
3 Comments » RSS 2.0 | Sphere it!
November 11th, 2005 11:17:22 am pst by
Sterling Camden
The Synergy/DE debugger is a command-oriented tool that does not provide any mechanism for logging its output to a file. That can be especially frustrating on Windows, because the debugger only displays the last 25 lines of output, so you can easily lose track of what went on before. But there is good news. I just saved a bunch of money on my — no, Sorry. There is a way to get this output to a file as you go.
When the output from dbr.exe is redirected to a file or a pipe, the debugger’s output goes there, too. It also works for redirected input, but that doesn’t help us here (although it could possibly help with automated debugging…hmmm). Anyway,
dbr -d myprog > myprog.log
isn’t very useful, because then you can’t see the debug output as you are running the debug session. However, there is a utility that first appeared on UNIX called ‘tee’. The tee utility sends its standard input to standard output, and also to any filename specified as a command argument. There are many versions of tee available, but if you need a free one for Windows, click thou hither. Using tee, the following
dbr -d myprog | tee myprog.log
sends the output of the debugger to the console as well as to myprog.log. On Windows, this has an interesting effect. You must focus the debugger window to enter commands, but the output goes to the console window. So, I usually place them one above the other so I can see what is going on. Not so on UNIX or OpenVMS, where all of the I/O goes to/from the terminal. On the other hand, the log file on Windows only contains the debugger commands and output (and any low-level terminal I/O the application might perform), because UI Toolkit output is not redirected. That makes the log file much more comprehensible than on UNIX/OpenVMS, where all of the application’s screen I/O is included in the file as well. UNIX and OpenVMS would also include any session with the window debugger (WINDBG at the debugger prompt), while on Windows any attempt to bring up the window debugger is ignored when output is redirected.
Another perhaps better solution to this problem is to use the remote debugging facility in conjunction with a Telnet client that allows you to record its session. Here is a batch file that will start a Synergy/DE program in remote debug mode on port 2500, then attach to it via Microsoft telnet, logging the output to debug.log:
@echo off
start dbr -rd 2500 %*
telnet localhost 2500 -f debug.log
This approach works nicely because both debug input and output will go to the console window. You can also use a similar approach with a program running on UNIX or OpenVMS, and avoid getting all of the application screen I/O in the log file. Only the content of the telnet session (the debugger’s I/O) will be included.
Posted in OpenVMS, SynergyDE, Unix, Windows |
No Comments » RSS 2.0 | Sphere it!
November 9th, 2005 5:10:20 pm pst by
Sterling Camden
The downloadable code below contains the source and executable for a simple ‘tee’ utility for Windows. The tee utility faced its first fairway on UNIX platforms, and has been ported to Windows by other providers of UNIX-style utilities. While my version may not be technically on a par with the MKS Toolkit version, mine definitely tops the leader board for price/performance ratio.
Now let’s sink the golfing puns, because the name for the tee utility actually derives from plumbing. Input and output can be ‘piped’ from one process to another on UNIX and on Windows, and the tee utility creates a tee in the pipe. Thus, in addition to sending output to standard out, you can also redirect it to zero or more files — very useful for keeping a log of a process while simultaneously being able to view its progress and/or send its output on to somewhere else. For example:
my100steps.bat | tee my100steps.log
can execute all 100 steps and send the output to the console while at the same time writing the output to my100steps.log.
The version you can download below uses the Microsoft .NET Framework (built using Visual Studio .NET 2008), and provides an example of using managed code in C++. It also demonstrates a few of the capabilites of the System::IO::StreamWriter and System::Console classes.
Jeroen Pluimers converted this to C# so it could run on Windows XP Embedded.
For a version in Ruby, go here.
UPDATE 2009-07-27: Added -a (or –append) option as the first argument only to append files rather than overwriting them. Also changed to a Unicode build under VS 2008.
UPDATE 2009-08-18: Upgraded syntax to eliminate /clr:oldsyntax and added an event handler for CancelKeyPress to ignore Ctrl+C, so the originating program in the pipe can handle it instead.
UPDATE 2010-01-25: Changed to use BinaryReader and BinaryWriter to eliminate CR/LF problems that resulted in double-spacing some forms of output. Thanks to Anonymous Coward for the suggestion below.
UPDATE 2010-01-28: Included more suggestions from Anonymous Coward. Use tee --help to see available options.
Posted in .NET, C and C++, Wildly popular, Windows |
30 Comments » RSS 2.0 | Sphere it!
September 13th, 2005 4:28:28 pm pst by
Sterling Camden
Having trouble with the event-driven programming model and Synergy/DE? Well, at least you’re not alone. Many Synergy/DE applications have evolved from old DIBOL programs that were anything but event-driven. Making the transition to the event-driven model promoted by the Synergy/DE Toolkit can be daunting. To compound the problem, the event model inherent in Microsoft Windows contains some significant paradigmatic differences that can create even more challenges for the Synergy/DE developer on that platform.
I wrote a white paper for Synergex on this topic. You can find it in the Synergex Virtual Library on their web site at http://www.synergex.com/pdf/EventModelW.pdf. This paper discusses the event-driven programming model both in abstract terms and specifically as it applies to Synergy/DE. It also draws parallels between the event models in Synergy/DE and other language platforms.
The downloadable code below was created for the Synergex SPC 2002 to demonstrate the difference between modal and non-modal applications, and to give concrete examples of how to implement the latter. It also includes some useful Windows-specific features.
Note: this example was recently updated to make use of features available in Synergy/DE version 8.3, and will no longer work with previous versions.
Posted in ActiveX, OpenVMS, SynergyDE, UI Toolkit, Unix, Windows |
No Comments » RSS 2.0 | Sphere it!
September 13th, 2005 4:25:12 pm pst by
Sterling Camden
The Synergy/DE Toolkit does not provide much support for container/child relationships between windows, with the exception of tab set containers. However, generic containers can be very useful for presenting a unified interface made up of diverse elements, such as input windows, lists, ActiveX controls, and even tab sets. Download the code below to obtain a suite of routines to enable container/child relationships, and to deal with the issues they present. Some of these issues include tabbing order, activation, clicking between child windows, and many others. These routines also contain some good examples of using advanced Synergy/DE features such as dynamic memory, RCB dynamic routine calls, macro expansion, window events, and more.
Most of the important code and comments can be found in container.dbl. The file container.def is an include to be used by client routines. The files sample.dbl and sample.wsc comprise a sample client program. Routines are best compiled using -T to avoid passing null arguments created by macro expansions.
Note: this example was recently updated to make use of Synergy/DE version 8.3 features, and will no longer work with previous versions.
Another note: Synergy/DE version 9 plans include a much more robust version of container windows that will also be cross-platform compatible.� If you can wait for that release, you’d be far better off.
UPDATE: Synergy/DE version 9 has been released, and it includes a much more robust version (which was written by yours truly).
Posted in SynergyDE, UI Toolkit, Windows |
1 Comment » RSS 2.0 | Sphere it!
September 13th, 2005 4:25:12 pm pst by
Sterling Camden
To do very much at all with the Windows API, you need access to window handles. Window handles are very much like Synergy window ID’s, except that they aren’t. A window handle uniquely identifies each window on the desktop, including the desktop itself and any component windows (windows within windows). Most applications in Windows contain many component windows, and a Synergy application is no exception. Besides the obvious container window and Synergy windows, every input field is represented by one or more component windows. Field prompts and display-only fields also have unique handles, as do drill buttons, hyperlinks, and standard buttons.
The downloadable code below includes routines for retrieving the window handles of Synergy windows, lists, buttons, and input field components (field controls, display-only fields, prompts, hyperlinks, and drill buttons). For complete comprehension, see the copious comments contained therein.
Note: this example was recently updated to make use of features available in Synergy/DE version 8.3, and will no longer work with previous versions.
Posted in SynergyDE, UI Toolkit, Windows |
No Comments » RSS 2.0 | Sphere it!
September 13th, 2005 4:25:12 pm pst by
Sterling Camden
Sometimes in a UI Toolkit input window, when the user changes the value of a field, you want to be able to automatically skip over the next field without disabling it or changing it to read-only. However, you don’t want to do that if the user left the field by clicking on a specific field or by pressing Shift-Tab to go to the previous field.
The downloadable code below demonstrates how to determine what field the user is trying to access when the current field’s change method fires. The main-line program is in tfocus.dbl, which also contains the change method and the all-inportant routine get_focus_field. Routines for obtaining window handles are in gethandle.dbl, which is also featured in another topic, Retrieving window handles of Synergy components
Note: this example was recently updated to use features available in Synergy/DE version 8.3, and will no longer work with previous versions.
Posted in SynergyDE, UI Toolkit, Windows |
No Comments » RSS 2.0 | Sphere it!
May 3rd, 2005 10:29:18 am pst by
Sterling Camden
While Synergy/DE gives you control over the color of Synergy windows, it does not provide access to the color of the application background area. This always defaults to the current Display/Appearance setting for “Window background”.
The best solution to this problem is to place a borderless window at pixel position 0,0 and make sure that it fills the application space. In the example you can download below, we size the window to the size of the screen. This insures that even if the user maximizes the application window, no area of the background will peek out from behind our window. The example is written specifically for Windows platforms. The same approach would work for color-enabled cell-based environments, with the Windows-specific code commented out.
The only downside to this approach is that any text displayed in the application background (via WRITES or DISPLAY to the terminal channel) will not be visible, because it is occluded by our background window. Instead, you must display it to the background window after sizing the latter appropriately. Because of this restriction, you might think that the best solution would have been to subclass the application window, as in the topic “Subclassing Synergy windows”. But as it turns out, there is no way for your subclass procedure to gain access to the text that should be displayed in the window, and the inherited Synergy method for displaying the text would overwrite the background color for the area that the text occupies.
Posted in SynergyDE, UI Toolkit, Windows |
No Comments » RSS 2.0 | Sphere it!