yoy.be "Why-o-Why"

2005 ...

januari februari maart april (1) mei juni (16) juli augustus september (12) oktober (14) november (8) december (3)

Application without forms.

2005-06-08 19:36  i87  delphi  [permalink]

One type of 'application without forms', is using the {$APPTYPE CONSOLE} setting to replace the default {$APPTYPE GUI}. When using Write and WriteLn the output is sent to a command prompt box, either the one the application was started in, or a new one if the application is started from the graphical environment (GUI).

If no commant prompt window is needed, and all you need is your exe running, you really end up with an application without forms. If you open the project source (the .dpr file) from the menu: Project > View Source, or with Ctrl+F12, you will see these lines:

Application.Initialize;
Application.Run;

Application.Initialize calls initialization some units require to be done right before the application starts, e.g. when using COM objects. Application.Run loops until the application is terminated, and processes incoming windows messages. If you add forms or datamodules, Application.CreateForm calls are added inbetween these two.

Sometimes, when using an application without forms, you get a button on the taskbar anyway. This is done every time Application.Handle is used, e.g. when using Application.MessageBox. If you don't want this, you might consider not using Application (if you don't include the Forms unit in the project the final exe-file could be much smaller!) but that might create a number of other problems. Another solution is this code, executed in the start-up code.

ShowWindow(Application.Handle,SW_HIDE);

By using the Handle property, the task-bar button is created, and by using the Windows function ShowWindow you can hide this button without changing the internal states of the Application object.

This task-bar button actually has a seperate right-click menu only with options Restore, Minimize and Close, that tie in to the Application object, which is different to the default right-click menu (SystemMenu) that has Move and Resize also. To have a taskbar-button for each window, see the CreateParams trick.


Taskbar-button per form in an application

2005-06-08 20:41  i89  delphi  [permalink]

If you want each form in an application to have a taskbar-button of its own, you need to add this code somewhere between the private and public section of the class declaration of your TForm descendant type:

protected
  procedure
CreateParams(var Params: TCreateParams); override;

At the bottom add this (where Form1 is the name of your form):

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent:=GetDesktopWindow;
end;
The virtual CreateParams procedure defined by the base TForm class, is used to modify the parameters used to call the Windows functions to do the work, before creating the window on screen. By setting the parent window to the desktop, a taskbar-button appears, with the icon and caption of the form. It also has the full default SystemMenu with all the options (according to the BorderIcons property of the form). The SystemMenu on the taskbar-button that is created by/for the Application object, is typically missing the Move and Size options.

Application version: alternative to GetFileVersionInfo

2005-06-08 22:05  i93  delphi  [permalink]

GetFileVersionInfo can have trouble with your executable being locked. Normally it doesn't, but still, if you know when starting an application, all resources in the exe-file are loaded into memory, it makes no sense to re-read the exe-file to get to the version resource data.

There is a resource type RT_VERSION. A ready-made standard-Delphi object TResourceStream provides access to the version data. VerQueryValue can read this data for you. Strangely enough you need to copy the data for it to get accessable, I copy it to a TMemoryStream here:

uses Windows,Classes,SysUtils;
var
  verblock:PVSFIXEDFILEINFO;
  versionMS,versionLS:cardinal;
  verlen:cardinal;
  rs:TResourceStream;
m:TMemoryStream;
  p:pointer;
  s:cardinal;
begin
  m:=TMemoryStream.Create;
  rs:=TResourceStream.CreateFromID(HInstance,1,RT_VERSION);
  m.CopyFrom(rs,rs.Size);
  rs.Free;
  m.Position:=0;
  if VerQueryValue(m.Memory,'\',pointer(verblock),verlen) then
    begin
      VersionMS:=verblock.dwFileVersionMS;
      VersionLS:=verblock.dwFileVersionLS;
      AppVersionString:=Application.Title+' '+
        IntToStr(versionMS shr 16)+'.'+
        IntToStr(versionMS and $FFFF)+'.'+
        IntToStr(VersionLS shr 16)+'.'+
        IntToStr(VersionLS and $FFFF);
    end;
  if VerQueryValue(m.Memory,PChar('\\StringFileInfo\\'+IntToHex(GetThreadLocale,4)+IntToHex(GetACP,4)+'\\FileDescription'),p,s) or
       VerQueryValue(m.Memory,'\\StringFileInfo\\081304E4\\FileDescription',p,s) or //nl-be?
       VerQueryValue(m.Memory,'\\StringFileInfo\\040904E4\\FileDescription',p,s) then //en-us?
     AppVersionString:=PChar(p)+' '+AppVersionString;
  m.Free;
end;

The text info in the version resource data is stored per locale-id/codepage-id combination (I haven't seen any version data blocks with more than one of this combinations, but then again, I haven't seen that much binary data of versionresourcedatablocks) so there's the option of picking up the currently valid LCID, or have some default (nl-be in my case, $0813, and internationally default $0409 also). The Delphi Project Options dialog, version tab, has a locale selection, so if you're sure about which one you're using there, you might just use that one in a single VerQueryValue in the last if statement.

Application version: alternative to GetFileVersionInfo

2005-06-08 22:06  r48  delphi  [permalink]

Application version: alternative to GetFileVersionInfo

in the mean time I found out a dynamic array of bytes works just as well to copy the version resource data to, but here I use a TMemoryStream which does the trick also.

ExitWindowsEx and setting the privilige for it, yourself!

2005-06-08 22:11  i94  delphi  [permalink]

ExitWindowsEx throws a privilege not set error by default, but there's a way to set this required privilege:

procedure RebootComputer;
var
 th:THandle;
 lid:Int64;
 tp,tpx:TTokenPrivileges;
 tpc:cardinal;
begin
 if not(OpenProcessToken(GetCurrentProcess,TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,th)) then
  RaiseLastOSError;
 if not(LookupPrivilegeValue('','SeShutdownPrivilege',lid)) then
  RaiseLastOSError;
 tp.PrivilegeCount:=1;
  tp.Privileges[0].Luid:=lid;
  tp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
 
 tpc:=0;
 if not(AdjustTokenPrivileges(th,false,tp,SizeOf(tp),tpx,tpc)) then
  RaiseLastOSError;
 
 if not(ExitWindowsEx(EWX_REBOOT,0)) then RaiseLastOSError;
end;

Answering to the WM_QUERYENDSESSION message

2005-06-08 22:16  i95  delphi  [permalink]

Check if the Messages and Windows units are included in the uses clause in the start of your unit.
Add this bit to the protected clause in the form class declaration. By default there is no need for a protected clause, so if it's missing, type protected at the same level of public or private.

procedure FormQueryEndSession(var Msg:TWMQueryEndSession); message WM_QUERYENDSESSION;

Declare the method something like this, adapt where neccessary to fit in your application.

procedure TMainWin.FormQueryEndSession(var Msg: TWMQueryEndSession);
begin
  Msg.Result:=1;
  PostMessage(Application.Handle,WM_CLOSE,0,0);
end;

We can't just call Close; because this method is called from the message loop from your application (have a look at TApplication.Run) and some things might need to happen after returning from this method. So we let Windows post us a close message so the internals of Application can do the close the correct way (something like simulating an Alt+F4).

If your application checks if the opened file has changed and needs to be saved, in the OnClose event or equivalent (never write clean-up-code in the OnClick of a 'Close' button or menuitem!!), you can do Msg.Result:=0; to let Windows know you're not ready to close and need the user to save the changes or press OK to discard the changes.


Enable dropping files onto your application

2005-06-08 22:18  i96  delphi  [permalink]

Check if the Messages and ShellApi units are included in the uses clause in the start of your unit.

Add a call to DragAcceptFiles in the initialization of the form (OnCreate or OnShow).

Add this bit to the protected clause in the form class declaration. By default there is no need for a protected clause, so if it's missing, type protected at the same level of public or private.

procedure FormDropFiles(var Msg:TWMDropFiles); message WM_DROPFILES;

Declare the method something like this, adapt where neccessary to fit in your application.

procedure TMainWin.FormDropFiles(var Msg: TWMDropFiles);
var
 i,FileCount,FileNameSize:integer;
 FileName:string;
begin
 FileCount:=DragQueryFile(Msg.Drop,-1,nil,0);
 for i:=0 to FileCount-1 do
  begin
   FileNameSize:=DragQueryFile(Msg.Drop,i,nil,0)+1;
   SetLength(FileName,FileNameSize);
   DragQueryFile(Msg.Drop,i,@FileName[1],FileNameSize);
   //skip closing #0 char
   SetLength(FileName,FileNameSize-1);

   //do something with FileName here...

  end;
 DragFinish(Msg.Drop);
end;

 

If you only need one file, you can skip the for loop and just use DragQueryFile(Msg.Drop,0,,);

Connect 4

2005-06-10 20:45  i107  freeware  [permalink]

[C4 icon] C4, short for Connect 4. The first version was a school project to employ all available techniques of artificial intelligence that applies to the algorhythm, to calculate the next best move. This version has updated graphics, a timer, and an attempt to show some internal numbers to help in competition training. This version also has a game-state load/save feature.

freeware/c4.zip

freeware

2005-06-10 20:46  freeware  freeware  [permalink]

---Here are a few applications I wrote, a few of them I use myself, a few were just for fun...

They're put public here as FreeWare, some are OpenSource. I haven't figured out yet if I need to put them here under a license or even which one. So for now they're all rights reserved and use em at your risk, though there's really nothing to fear because they really don't do more then they're supposed to do.

Anyway, if you really want to have a look at the SourceCode, let me know -- StijnSanders

(Click on these icons:)

[TreeBrowse] [DirDiff] [DirFind] [odo] [RE] [jsonDoc] [Connect 4] [CursorTime] [MetaClick] [MetaKeys][BarCode] [MailCount] [Ro] [Fa] [WebTop] [SideSwitch] [Drink]

AllSorts (shell extension)
Growthris
IconSuite
WikiEngine
TortoiseSVN icons
xxm
github.com/stijnsanders

BarcodeStuff

2005-06-10 20:48  barcode  delphi freeware  [permalink]

This is a little idea I had (after I had to do something similar at work, off course), and I built up into a test-utility to compare BarCode''''s with.

I noticed Delphi has a TBits object, it's a sort of TList, but only stores a list of bits (exposed as booleans). Really handy to store an encoded string of characters, and to start from to do something with it, e.g. generate a TBitmap, or HTML code, or anything really...

Have a look at the tester-utility (barcodestuff_exe.zip ~218KB) or the Delphi7 source (barcodestuff_src.zip ~14KB). It's really basic, not calculating CheckSum digits, and doing only basic checks on which strings it gets.


CodaBar, Code11, Code39, Code93, Code128, Interleaved2of5, UPC/EAN

Growthris

2005-06-10 20:50  i110  freeware  [permalink]

Growthris is a crazy Tetris with a twist. Not only is the gamespace vertically cyclic, it is expanding! But not the view! Keep track of what's where with a limited view, while downward motion of the bricks is speeding up!

freeware/growthris.zip

MailCount/PopCount

2005-06-10 20:51  i111  freeware  [permalink]

[MailCount icon]MailCount might come in handy if you want to follow the continuous flow of mail in your inbox, but don't want to have Outlook open all of the time.
This application still needs Outlook though, so you best have Outlook minimized. If you don't have Outlook open, ActiveX will start it in the background.

If there is a "MailCount.wav" file present in the directory where you save this exe, it will be played whenever the count of unread mails increases.

If your 'unread mail count' rises above 100, the number divided by 10 is shown in blue.

In the zip is also a version that connects to POP3: PopCount.exe. When run the first time, it shows "00" in red, indicating an error. Double click to enter the POP3 login data. Your password is saved encrypted in the PopCount.ini file.

freeware/MailCount.zip

dsControls: dsWebTreeView

2005-06-10 20:52  i112  freeware  [permalink]

dsCt_1.exe, is a self-extracting RAR that extracts the files to a Program Files directory, and starts the Microsoft register server. On some older windows versions, this call fails, and you have to register the OCX yourself.

Together with the main OCX, a directory with documentation html is provided, that uses the dsWebTreeView for navigation itself.

Use the OCX and the documentation to have a TreeView contol on your web-page. See the HTML source of the documentation for an example. (Or this site! example)


Odo

2005-06-10 20:53  odo  freeware  [permalink]

[Odo icon]Odo began as an attempt to write my own odometer, a counter of how much distance you travel with the mouse-cursor on screen. Since this kind of data takes some time to collect, I was more interested in when I did how much with the mouse. Later I added a keystroke-counter and a link to a local database, to be able to look up my history of activity.

As of version 0.4, the data link uses sqlite3.dll: odo_511.zip 646KB,
Keep using version 0.3 to use a data link based on OLEDB/ADO: odo_278.zip 338KB

bitcoin accepted

The graph displays the measured values with a combination of colors, at one minute per horizontal pixel:
  Upper graph:
  Green: Horzontal mouse movement
  Red: Vertical mouse movement
  Lower graph:
  Green: Keystrokes
  Red: Mouseclicks
  Blue: Application switches
Since these are the basic colors, overlapping dispay results in different colors: red and green make yellow, blue and green make light-blue (cyan), blue and red make purple (magenta), and all three make white.

freeware/odo_511.zip

Regular Expression

2005-06-10 20:54  i114  dotnet  [permalink]

[RE icon]RE, short for Regular Expression is a tool to build advanced structures that use, among other things, [[Regular Expressions]] to transform text. I didn't spend too much time thinking about a decent name for the application and a first version only operated on the clipboard (and was called CBRE: Clipboard Regular Expression), so I got stuck with 'Regular Expression'. Another rule I broke is that you can't really operate it with the keyboard only. In return there is a really nifty drag-and-drop way of moving items around and connecting them, really a nice way to visualise the structure you're working on, and easy to have more items than needed around when building or debugging.

Starter's guide:
» Download and install RE_setup.exe (~551KB), and have the wizard start RE. Hit the 'Register Regular Expression data file type' button on the settings dialogs. This registers the .rxe file format with Windows to open the files easily.
» The application starts with an empty workspace, use the Add menu on the main-menu, or use the right-click menu in the workspace that has all the items also. Pick an item, e.g. Input/Output > Clipboard, and another, e.g. Input/Output > Viewer. Now drag from one of the sunken rectagles, called linkpoints, to the other to establish a link. If you now hit Run, the text-contents of the clipboard, if any, are shown in the Viewer.
» To move bigger structures around, drag on the open workspace, to get a running ants rectangle to select multiple items. When a structure is bigger than your screen and you need to scroll, hold Ctrl down and drag the workspace around.

Update 2014-01-01: This project is now open-source! https://github.com/stijnsanders/RE

http://yoy.be/freeware/RE_setup_350.exe

TreeBrowse

2005-06-10 20:55  i115  freeware  [permalink]

[TB icon] TreeBrowse (~585KB) was a small project at first to have something better than a one-dimensional browse history (back, forward). By building a tree-structure as you browse through pages (and surf the web), you have a better view of how you got to where you are.
And there's more. On summary pages with links, you see a number of things you want to read, but when done with the first, you can't find the other any more. Press the links whil holding Ctrl, and nodes are added to the tree for later. Then view the items at you own pace. To clarify the overview, mark nodes with different icons, or drag and drop them to other places in the tree.

http://yoy.be/freeware/TB_setup.exe