Jump to content
Tuts 4 You

Delphi 7 and Createthread API


ToMKoL

Recommended Posts

Posted

Hi all

I'm trying to convert this small c snippet to delphi 7 code but without success for now. If any delphi coder could help I'll be gratefull.

HANDLE hthread;

hthread = CreateThread(0, 0, &animate, hWnd, 0, 0)

DWORD WINAPI animate(HWND hWnd)
{
	unsigned char wincaption[32];
	unsigned int i;
	SendMessageA(hWnd, WM_GETTEXT, 32, (LPARAM)wincaption);
	do
	{
		for(i=0;i<20;i++)
		{
			if (((wincaption[i] >= 0x41) && (wincaption[i] <= 0x5A)) || ((wincaption[i] >= 0x61) && (wincaption[i] <= 0x7A)))
				wincaption[i] ^= 0x20;
			SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)wincaption);
			Sleep(500);
		}
	}
	while (1);
}

And my delphi attempt:

hthread : THandle;

hthread := CreateThread(nil, 0, @animate, hWnd, 0, 0);

procedure animate(hWnd : HWND);
var
	wincaption: array[0..32] of char;
	i: integer;
begin
  SendMessageA(hWnd, WM_GETTEXT, 32, integer(pchar(@wincaption[0])));
 	while true do
  begin
	  for i := 1 to 23 do
   		begin
	    	if (((wincaption[i] >= $41) and (wincaption[i] <= $5A)) or ((wincaption[i] >= $61) and (wincaption[i] <= $7A)))
			    wincaption[i] := wincaption[i] xor $20;
   			SendMessageA(hWnd, WM_SETTEXT, 0, LPARAM(wincaption));
	    	Sleep(500);
   		end;
 	end;
end;

 

Posted
1 hour ago, ToMKoL said:

Hi all

I'm trying to convert this small c snippet to delphi 7 code but without success for now. If any delphi coder could help I'll be gratefull.

HANDLE hthread;

hthread = CreateThread(0, 0, &animate, hWnd, 0, 0)

DWORD WINAPI animate(HWND hWnd)
{
	unsigned char wincaption[32];
	unsigned int i;
	SendMessageA(hWnd, WM_GETTEXT, 32, (LPARAM)wincaption);
	do
	{
		for(i=0;i<20;i++)
		{
			if (((wincaption[i] >= 0x41) && (wincaption[i] <= 0x5A)) || ((wincaption[i] >= 0x61) && (wincaption[i] <= 0x7A)))
				wincaption[i] ^= 0x20;
			SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)wincaption);
			Sleep(500);
		}
	}
	while (1);
}

And my delphi attempt:

hthread : THandle;

hthread := CreateThread(nil, 0, @animate, hWnd, 0, 0);

procedure animate(hWnd : HWND);
var
	wincaption: array[0..32] of char;
	i: integer;
begin
  SendMessageA(hWnd, WM_GETTEXT, 32, integer(pchar(@wincaption[0])));
 	while true do
  begin
	  for i := 1 to 23 do
   		begin
	    	if (((wincaption[i] >= $41) and (wincaption[i] <= $5A)) or ((wincaption[i] >= $61) and (wincaption[i] <= $7A)))
			    wincaption[i] := wincaption[i] xor $20;
   			SendMessageA(hWnd, WM_SETTEXT, 0, LPARAM(wincaption));
	    	Sleep(500);
   		end;
 	end;
end;

 

Hi

Following code is not exact translation but can help you :

Spoiler

function animate(hWnd: PDWORD): DWORD; stdcall;
var
  TextLength: Integer;
    wincaption: WideString;
    i: integer;
  hndl : NativeUInt;
begin
  hndl := hWnd^;
  TextLength := SendMessage(hndl, WM_GETTEXTLENGTH, 0, 0) + 1;
  wincaption := StringOfChar(#0, TextLength);
  GetWindowText(hndl, PWideChar(wincaption), 255);

     while true do
  begin
      for i := 1 to Length(wincaption) do
       begin
          if (((Ord(wincaption[i]) >= $41) and (Ord(wincaption[i]) <= $5A)) or ((Ord(wincaption[i]) >= $61) and (Ord(wincaption[i]) <= $7A))) then
           wincaption[i] := WideChar(Ord(wincaption[i]) xor $20);

      SetWindowText(hndl, PWideChar(wincaption));
      UpdateWindow(hndl);
          Sleep(500);
       end;
     end;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  hthread : THandle;
  hndl : HWND;
  FThreadID : cardinal;
begin
  hndl := Form1.Handle;
  hthread := CreateThread(nil, 0, @animate, @hndl, 0, FThreadID);
end;

 

Posted

I normally setup a thread something like this...

  FWorkerThread := TBackgroundThread.Create(true);
  FWorkerThread.FreeOnTerminate := true;
  FWorkerThread.OnTerminate := HandleOnTerminate;
  FWorkerThread.Resume;

and then use this for your execute thread code...

procedure TBackgroundThread.Execute;

and this if you want to do anything after the thread is completed...

procedure TfrmMain.HandleOnTerminate(Sender: TObject);

 

Posted

Thanks for reply but forgot to mention that I don't use forms and try as much as I can to stay with winapi. I'm using external resources with dialog to do my stuff.

 

@h4sh3m Your reply helped a lot but still can't compile my project. I did this changes:

var
  hndl : HWND;

hndl := hWnd;
hthread := CreateThread(nil, 0, @animate, @hndl, 0, 0);

procedure animate(hWnd : PDWORD);
var
  ...
  wndhndl : NativeUInt;
begin
  hndl := hWnd^;
  ...

But now retrive this error message - 'Types of actual and formal var parameters must be identical'.

 

My delphi coding skills are limited so I test all solution that I can google but till now nothing worked.

Posted

It's hard to "debug" your code by seeing just a small code snippet. It would be nice if you could post the entire project so that it can be opened in Delphi and compiled right away..
Anyway, I think I see 2 problems:

1) This is how CreateThread is defined in Delphi9 (sorry, no D7 here):

function CreateThread(lpThreadAttributes: Pointer;
  dwStackSize: DWORD; lpStartAddress: TFNThreadStartRoutine;
  lpParameter: Pointer; dwCreationFlags: DWORD; var lpThreadId: DWORD): THandle; stdcall;

See the last parameter, lpThreadId? It's declared as "var". Therefore you may not use a constant 0, even if you don't care about the thread id.  You should use a variable instead.

Something like this may work:

var
  hndl : HWND;
  threadId : DWORD;

hndl := hWnd;
hthread := CreateThread(nil, 0, @animate, @hndl, 0, threadId);


2) Thread procedure must be defined as "stdcall". Compiler might not complain but your thread will crash because by default it will expect hWnd to be passed via registers.

procedure animate(hWnd : PDWORD); stdcall;

 

Posted (edited)

Kao beat me to it but I think the ThreadId needs to be Cardinal not DWORD for Delphi 7 :)

Edited by NOP
Posted (edited)

Thanks guys for replies. Will check them. I'm, attaching full project. Just don't blame me for shitty code. Coded this in few houres at work (have plenty free time right now) using only examples found in google. To test You'll need to uncomment code for thread. Also any optimizations to this code are more than welcome. And please be aware that I'm using archaic d7 personal version.

sdfkgme15.zip

 

Small update - almost made it work. Thanks for tips with 'ThreadID'. This was the key. Now have problem with dereferncing pointer in thread.

hthread := CreateThread(nil, 0, @animate, PDWORD(hWnd), 0, tid);

procedure animate(hWnd : PDWORD); stdcall;
...
SendMessageA(hWnd^, WM_GETTEXT, 32, integer(pchar(@wincaption[0])));
...

and this is translated by compiler like:

mov eax, hWnd
push eax
...
call CreateThread

thread proc
mov edi, dword ptr [ebp+8] -> edi holds hwnd
...
mov eax,dword ptr [edi] -> here is error it should compile to mov eax,edi

 

Small update2 - made it work partially:

hthread := CreateThread(nil, 0, @animate, PDWORD(hWnd), 0, tid);

procedure animate(hWnd : HWND); stdcall;
var
	wincaption: array[0..32] of char;
	i: integer;
begin
  SendMessageA(hWnd, WM_GETTEXT, 32, integer(pchar(@wincaption[0])));
 	while true do
  begin
	  for i := 0 to 22 do
   		begin
	    	if ((ord(wincaption[i]) >= $41) and (ord(wincaption[i]) <= $5A)) or ((ord(wincaption[i]) >= $61) and (ord(wincaption[i]) <= $7A)) then
			    wincaption[i] := ord(wincaption[i]) xor $20;
   			SendMessageA(hWnd, WM_SETTEXT, 0, LPARAM(@wincaption[0]));
	    	Sleep(500);
   		end;
 	end;
end;

This works except the line - 'wincaption[i] := ord(wincaption[i]) xor $20;'. It gives me error about incompatible types char and integer.

Edited by ToMKoL
added more information
Posted

Manage to make it work like I wanted. Working package included. Thanks guys for all help.

sdfkgme15.zip

  • Like 1

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...