04 May, 2007

Delphi 2007 - how to install packages and components

Hello. As I see in my statistics one of my old posts, Creating a new component package in Delphi 2005 (Win32), is very popular. Also I have notice that with appearing of Delphi 2007 for Win32 Steve Trefethen wrote a very nice tutorial which shows How to Install Components in the Delphi IDE and Nick Hodges made a great streemcast on the same topic. Now this theme is fully uncovered!

Come again!

27 April, 2007

Subversion, Continuous Integration

Hello all! As I was saying in one of my previous posts, I am going to write some articles about Continuous Integration, Subversion (SVN) and other related things. But looking on some circumstance I decided not to write about those things (well, however I'll write some short notes). The reasons are pretty simple - few guys already started to write on this topics (here and here). They are much stronger in English than me and more advanced in this field. That's why I decided to make way for them. And therewith I don't like to clone blog posts.

PS: don't forget to read a very good book about Subversion. There is also a Russian version of this book.

Come again!

-- 4/05/2007 - New useful link
Delphi and SubVersion

24 April, 2007

Problems with ASP.NET debugging in BDS 2006

Hello people! Today I want to talk about annoying things that occurs when you try to debug ASP.NET applications in Delphi 2006.

At first small prelude. Most of you are probably like me first install all necessary applications on just installed Windows Xp and only after this remember that IIS supposed to be installed before .NET framework has been installed because if you install IIS after the .NET Framework then ASP.NET will not be registered properly in IIS and you will have some problems with ASP.NET.

In order to solve this issue you should do the following:

  • Start console and browse to the "C:\WINDOWS\Microsoft.NET\Framework\(your framework version)";
  • run aspnet_regiis.exe with -i parameter;

Now ASP.NET is registered but still not in the way which will satisfy me. Why? Well, it is simple. First, if you take a look at the Documents tab in the Properties window of any ASP.NET application you won't see Default.aspx item in the Default documents list. Yes, I know that it could be easily added but after all it supposed to be there by default. Second, with out any reason ASP.NET applications works very slow and sometimes, when you try to debug them from BDS 2006, you receive some weird errors. So if you don't want to have any doubts whose fault is this, yours or Microsoft, then the following should be done -uninstall ASP.NET and reinstall it again :) Don't worry, it won't take too much of your time. Just do next and you won't regret:

  • Once again start console and browse to the "C:\WINDOWS\Microsoft.NET\Framework\(your framework version)";
  • run aspnet_regiis.exe with -u parameter;
  • then remove ASPNET account from user accounts if it is still there (Press Start>Run; type control userpasswords2);
  • run aspnet_regiis.exe with -i parameter;

Now everything will work like out of the box. But it is not the end :)

The only thing left to do is to uncomment tags of the <assemblies> and <httpModules> sections of the Web.config file of your ASP.NET application. And now everything works like it supposed to work! Hurray! Everybody happy!

Stay tuned!

22 April, 2007

New version of a great color picker tool - AdesClrPicker

Do you know that new version (2.0) of this very easy to use tool for picking colors has been released? Who said NO??? How this could happen?! Quickly check it out! A lot of new features has been introduced. You can see the list of changes and download AdesClrPicker v2.0 from here. This is a must have tool!

19 April, 2007

Interesting sample from the book

Hello. Yesterday I was reading one nice book about ASP.NET - ASP.NET: Tips, Tutorials and Code. In one chapter I have found an interesting code sample which shows how to work with Hashtable. Here is a piece of it:

Dim htSlaries As New Hashtable()

htSalaries.Add("Bob", 40000)
htSalaries.Add("John", 65000)
htSalaries.Add("Dilbert", 25000)
htSalaries.Add("Scott", 85000)
htSalaries.Add("BillG", 90000000)
' Then show this list in the label
htSalaries.Remove("BillG")
 

Now guess who is BillG?! :) Firstly he gets his salary on paper and then employers change their mind :) Probably they decided that he has got enough already.

17 April, 2007

First impression about Delphi 2007

Hello all! I finally have installed Delphi 2007 about an hour ago and now make some testdrive. Here is my first impressions:

Positive:

  • New installer became nicer and faster;
  • BDS 2007 starts faster then BDS 2006 (not pretty much but still faster);
  • The second start of BDS 2007 is definitely much faster than BDS 2006;
  • Help looks better too (hope the content became better too);
  • Finally we have Build Events!;

Negative:

  • New installer didn't want to run properly from my D: partition (Windows installed on C:);
  • Text size button in the help doesn't work (actually it works but the only thing that changes is bullets size; the text size remains the same);

More will be later!

Conclusion:

First impression is pleasant so far.

13 April, 2007

The Returning

Hello-hello! Sorry for the long period of silence. I have been out of the city and had not much opportunities to be online. Also I had to finish few projects. So in one word - busy :)

Well during that nice period I have visited the capital (Kyiv). I have spent such a great time there even in spite of the fact that I have been in the business trip :). I spent in Kyiv 3 wonderful weeks and have passed very interesting courses - Visual Studio .NET. So from now I am starting to dig dipper into the world of .NET and planing to write on this blog not only about Delphi but also about C# and .NET.

At the courses I have started to learn C#. Nice programming language but I am interesting in it only as a language for writing ASP.NET applications. All the rest I'll write exceptionally on Delphi (Delphi for .NET). Even ASP.NET applications I write in Delphi (code behind) but sometimes it is necessary to write some code in the aspx file and exactly for such situations I need to know CSharp (or at least VB.NET).

Currently I am playing with few very interesting technologies: CVS, Subversion (well now I know precisely that Subversion is better than CVS and I'll use exactly Subversion; Continuous Integration), XML Documentation and OpenTools API. More about this later.

And probably the most important thing - I am going to move my blog to the new place! Hurray! New online home for my blog will be at www.iskomorokh.com. For now this place is empty but soon everything will change. The reasons of this move are pretty obvious:

  • Desire to have more features then Blogger can give and more styles (own implementation);
  • total control;
  • great chance to have practice;
  • many other :)

See you.

18 February, 2007

How to remove an application button from the taskbar in Delphi?

This is a question which each Delphi programmer ask himself at least once in his life. If you use Google or any other search engine you will easily find this solution:


1 procedure TForm1.CreateParams(var Params: TCreateParams);
2 begin
3 inherited CreateParams(Params);
4 with Params do begin
5 ExStyle := ExStyle or WS_EX_TOPMOST;
6 WndParent := GetDesktopwindow;
7 end;
8 end;

So now you definitely have a question: "If it is so easy to find a solution then why I am talking about this?" An answer is simple. I have merely encountered a situation when approach which has been shown above is not suitable and decided to share my solution of this case with you.

Well what is the intention of the problem? According to the MSDN if you add WS_EX_TOOLWINDOW to the window ExStyle then window will act like this:

WS_EX_TOOLWINDOW

Creates a tool window; that is, a window intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB. If a tool window has a system menu, its icon is not displayed on the title bar. However, you can display the system menu by right-clicking or by typing ALT+SPACE.

But my client asked me to remove the button from the taskbar and leave the ability to see the window in the ALT+TAB dialog. Thus I had to refuse from above method and create my own. The solution in principle is not hard. Here is the list of steps you should do if you want to achieve an appropriate behavior:

  1. Set FormStyle property of your form to fsStayOnTop (this helps us to hold our window on top of the rest windows of our application);
  2. Write next piece of code:
 1 type
2 TfrmSamples = class(TForm)
3 { ... }
4 public
5 procedure FormDeactivate(Sender: TObject);
6 { Public declarations }
7 end;
8
9 { ... }
10
11 procedure TfrmSamples.FormCreate(Sender: TObject);
12 begin
13 { force floating window to be on top }
14 Application.OnDeactivate := FormDeactivate;
15 end;
16
17 procedure TfrmSamples.FormShow(Sender: TObject);
18 begin
19 ShowWindow(Application.Handle, SW_HIDE);
20 end;
21
22 procedure TfrmSamples.FormDeactivate;
23 begin
24 Application.BringToFront;
25 end;

According to the Borland help TApplication.OnDeactivate event occurs when an application becomes inactive therefore if we want to keep our window above all other applications (windows) then this is exec place to act.

That's all! Quick and easy.

If you have some other solution of this task please post them in the comments.

15 February, 2007

Global mouse hook in Delphi

Hello everyone!

On my primary job I have changed my mouse. At home I have A4Tech optical mouse with a scroll but on my job I have Genius mouse (optical and with a scroll as well). At home I use my scroll also as a middle button and when I press it the window which is under cursor getting minimized. It was easy to achieve this behavior because software which comes with my A4Tech mouse supports this functionality. Another case is my Genius mouse at work. Software which bundled with it does not allow to minimize the window under the cursor when the scroll button is pressed. Pity!

But solution always can be found! I decided to write a global mouse hook on Delphi which will intercept middle (scroll) button click (WM_NCMBUTTONDOWN and WM_MBUTTONDOWN messages), check if any top level window is under the cursor and if yes then minimize that window.

The code is pretty simple.

We need two projects: one - which runs the hook and then kills it; the other - the hook itself (it is supposed to be a DLL because it is a global hook). Nothing difficult (at least if you what is DLL and how to use them)!

Here is the mouse hook (WH_MOUSE) implementation:

library MiddleButton;

uses
Windows,
Messages;

const
MemMapFile
= 'Igor_thief';
type
PDLLGlobal
= ^TDLLGlobal;
TDLLGlobal
= packed record
HookHandle: HHOOK;
end;

var
GlobalData: PDLLGlobal;
MMF: THandle;

{$R *.res}

function HookProc(Code: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
CurrWND: THandle;
begin
if Code < 0 then
begin
Result :
= CallNextHookEx(GlobalData^.HookHandle, Code, wParam, lParam);
exit;
end; // if

if (wParam = WM_NCMBUTTONDOWN) or (wParam = WM_MBUTTONDOWN) then
begin
CurrWND :
= PMouseHookStruct(lParam)^.hwnd;
CurrWND :
= GetAncestor(CurrWND, GA_ROOTOWNER);
SendMessage(CurrWND, WM_SYSCOMMAND, SC_MINIMIZE,
0);
end; // if

Result :
= CallNextHookEx(GlobalData^.HookHandle, Code, wParam, lParam);
end;

procedure CreateGlobalHeap;
begin
MMF:
= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0,
SizeOf(TDLLGlobal), MemMapFile);

if MMF = 0 then begin
MessageBox(
0, 'CreateFileMapping -', '', 0);
exit;
end;

GlobalData:
= MapViewOfFile(MMF, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TDLLGlobal));
if GlobalData = nil then begin
// не смогди создать отображение
CloseHandle(MMF);
MessageBox(
0, 'MapViewOfFile -', '', 0);
end;
end;

procedure DeleteGlobalHeap;
begin
if GlobalData<>nil then
UnmapViewOfFile(GlobalData);

if MMF<> INVALID_HANDLE_VALUE then
CloseHandle(MMF);
end;

procedure RunHook; stdcall;
begin
GlobalData^.HookHandle:
= SetWindowsHookEx(WH_MOUSE, @HookProc, HInstance, 0);
if GlobalData^.HookHandle = INVALID_HANDLE_VALUE then
begin
MessageBox(
0, 'Error :)' , '' , MB_OK);
Exit;
end;
end;

procedure KillHook; stdcall;
begin
if (GlobalData<>nil) and (GlobalData^.HookHandle<>INVALID_HANDLE_VALUE) then
UnhookWindowsHookEx(GlobalData^.HookHandle);
end;

procedure DLLEntry(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH: CreateGlobalHeap;
DLL_PROCESS_DETACH: DeleteGlobalHeap;
end;
end;

exports
KillHook,
RunHook;

begin
DLLProc:
= @DLLEntry;
DLLEntry(DLL_PROCESS_ATTACH);
end.
And here is an implementation of the hook launcher:
unit RunMiddleButton;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;

type
TfrmMain
= class(TForm)
btnRunHook: TButton;
btnKillHook: TButton;
procedure btnRunHookClick(Sender: TObject);
procedure btnKillHookClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

procedure RunHook; stdcall; external 'MiddleButton.dll' name 'RunHook';
procedure KillHook; stdcall; external 'MiddleButton.dll' name 'KillHook';

var
frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.btnRunHookClick(Sender: TObject);
begin
RunHook;
end;

procedure TfrmMain.btnKillHookClick(Sender: TObject);
begin
KillHook;
end;

end.

If you don't know what is HOOK and how it works at all then you shoulf go and read MSDN.
Good luck! Study hard!

07 February, 2007

Debugging DLL in Delphi

Yesterday I spend about an hour to figure out how to debug DLL in Delphi. It is really long time considering that I was doing this before. Google didn't help me a lot because all I have found wasn't really helpful.

I have found this solution in the Internet:

Until up to Win2k, you had to set the HostApplication on Start=>Parameter to debug a DLL. This will not work on Windows XP. That Delphi will know the DLL if you run the program, you have to do the following:
The program must load the DLL. After this, press Ctrl-Alt-M in Delphi, to list all modules. Sometimes there will be the DLL with path.
Solution:
Right click on the DLL, select "Reload symbols" and set the full path to the DLL. Now the breakpoints should be active.
When the DLL will be compiled in the system path (directory in PATH) this problem don't occur.

Not bad! But I have discovered for myself more easy and fast way. Next steps need to be done:

  1. In the Project Manager make your DLL project active and press Ctrl+Shift+F11;
  2. In the Project Options window which just appeared select Debugger node and on the right side of the window in the Host Application field specify the host application (press Browse button and select the application which use your library) and then close the dialog by pressing the Ok button;
  3. Then simply press F9 and be happy!

BTW, it is also good to set up dependencies of your main application which use the DLL you want to debug. You can read about this here.

15 January, 2007

Color namespaces and their implementation in Delphi or any other programming language

There are few color namespaces (color models). Some of them are better in one field but worse in other. Sometimes it happens that you need to convert some color from one color model to another. This is exact situation which has happened to me. So I decided to find a little bit more information about color models which I need to work with. I went to Wikipedia and Google and found a lot of useful information and few code snippets. That made me happy … but not for long L

Well, here is the situation: there is one color which I need to convert from RGB color model to HSL (HLS) and back but for all that I need all the work to be done with whole numbers. It seems that the task is not complicated. But I have been put in horror by the fact that all the versions of the source code I have found in Internet use different approaches to present color formats. Some represent RGB values as 0..255 but the other as 0..1; HLS values as H – 0..360, S и L – 0..1 or H – 0..239, S и L – 0..240 (e.g. Microsoft). I have seen few another modifications. Weird – isn’t it?

But this is yet far not the end of the story. Later I have been put into more horrible horror. Having tested some variants of a code I have discovered that returned results from the different versions of code almost completely mismatch, though the input was the same for all of them. Suddenly one interesting question came to my mind. Is it possible that Borland (or I should better say CodeGear) or Microsoft do not give us some solution for this, it would seem basic task? And I have appeared right! Both giants give us necessary routines. CodeGear gives us ColorRGBToHLS and ColorHLSToRGB respectively which can be found in GraphUtil unit. You can get access to the Microsoft functions ColorHLSToRGB and ColorRGBToHLS with the help of ShlwAPi unit. Hurrah! – I exclaimed, but again it was too early. Once again a great surprise expected me.

This time the thing was that at the first glance everything seems to work, and even looks like the truth, but it turned out, that as a result – this is just at first glance. The fact is that few colors in RGB model has been found which can be converted into HLS model without any problem, but it is impossible to get the same RGB color back from the HLS model. You can easily make sure in it. Simply run MS paint and enter these RGB values R=196, G=136, B=248 in the Select Color dialog. Remember HLS values. Now change the color to some other. And now enter HLS values which you remembered. Then compare resulted RGB values with RGB values you have been entering at the beginning. See?!

I have found a bug in the ColorRGBToHLS procedure which is in the GraphUtil and reported it in QC (QC#37436: GraphUtil.ColorRGBToHLS). It was rounding issue. I thought that this will save the situation but I was wrong. The ColorHLSToRGB routine was buggy too (QC#37572: conversion issue between ColorRGBToHLS and back ColorRGBToHLS (GraphUtil)) but this time the problem hides in formulas.

Conclusion:

  • I still don't understand - is there any standard in this field? If yes, why nobody follows them?
  • Don't try to remove those bugs I described above. The problem is not in code - the problem is in the formulas. Yes, yes ... I am saying that HLS color model is buggy!
  • No matter which code version you will use (CodeGear, Microsoft, anybody else) - they all works wrong!

02 January, 2007

Happy New Year!

Happy New Year!!!