Finding the correct handle of Notepad++ to use in SendMessage() - winapi

I'm in my first try with WinAPI and I am trying to send some text from a Delphi program (well Lazarus) to Notepad++.
I already found a good example to use simple Notepad, that goes like this :
Procedure TForm1.Button1Click(Sender: TObject);
var Var1, Var2 : HWND;
Begin
Var1 := FindWindow('notepad', nil);
Var2 := FindWindowEx(Var1, FindWindow('Edit', nil), nil, nil);
Clipboard.AsText:='This is some sample text.';
SendMessage(Var2, WM_PASTE, 0, 0);
End;
So this works fine for Notepad.
Now I would like to adapt it to use with any other program.
Taking Notepad++ for example, how do I find it's equivalent to 'Edit' used there in the FindWindowEx() ? Or let's say the correct cell and workbook to paste in LibreOffice Calc?
Any samples or clues?
Thanks.

Related

Scan file after start of programm

I've added a TToggleBox in my Lazarus tool and now i want it to be set according to the existence of a string in a file located in the same directory. Therefore i want Lazarus to the check the file for the string right after the programm has started. If it cointains the string (for example "hello world") it should set the Caption of ToggleBox1 (see underneath) to "Activated" and if the string is not present to "Deactivated". How do i do this?
TToggleBox:
procedure TForm1.ToggleBox1Change(Sender: TObject);
begin
if ToggleBox1.Checked then
begin
ToggleBox1.Caption:='Deactivated'
end
else ToggleBox1.Caption:='Activated';
end;
Also, after the caption togglebox has been set by the tool I want to interact with it furthermore. Meaning, when the string was not found and the Caption of the ToggleBox has been set to "Deactivated", i want to press the ToggleBox to start a cmd-script and set the Caption to "Activated" and reverse (if string found and Caption set to "Activated" by pressing the ToggleBox i want to set the Caption to "Deactivated" and start another cmd script). How can you do this?
You can use a TStringList to load the file from disk, assuming it is a textfile, then use the Pos() function to see if the stringlist's Text property contains the string of interest. For example:
function TextFileContains(cost AFileName, AString : String) : boolean;
var
StringList : TStringList;
begin
StringList := TStringList.Create;
try
Stringlist.LoadFromFile(AFileName); // Note: AFileName should include the full path to the file
Result := Pos(AString, StringList.Text) > 0;
finally
StringList.Free;
end;
end;
I assume you can work out how to use this function in your code to achieve the desired result. If not, ask in a comment.

"Group by" a certain folder in windows explorer

What I am trying to do is to crate a folder for my application, and to make sure each time a user enters this folder, it's grouped, like this:
except that the disks would be replaced by some folders/files.
so basically I'm trying to achieve exactly what "Group by" function does:
and I have to do this in my application with c/c++ code or a bat. I'm guessing this needs to be done in the registry, but I cannot find where. any idea?
thanks.
You must understand that changing of Explorer view mode with registry is dirty hack. So USE ON YOUR OWN RISK. TESTED ON WINDOWS 7 ONLY.
procedure SetFolderGroupBy(AParentWnd: HWND; const AFolder: UnicodeString; const AColumn: TPropertyKey; AAscending: Boolean);
var
Desktop: IShellFolder;
Attr: DWORD;
Eaten: DWORD;
IDList: PItemIDList;
Bag: IPropertyBag;
Direction: DWORD;
begin
OleCheck(SHGetDesktopFolder(Desktop));
try
Attr := 0;
OleCheck(Desktop.ParseDisplayName(AParentWnd, nil, PWideChar(AFolder), Eaten, IDList, Attr));
try
OleCheck(SHGetViewStatePropertyBag(IDList, 'Shell', SHGVSPB_FOLDERNODEFAULTS, IPropertyBag, Bag));
try
OleCheck(Bag.Write('SniffedFolderType', 'Generic'));
finally
Bag := nil;
end;
OleCheck(SHGetViewStatePropertyBag_(IDList, 'Shell\{5C4F28B5-F869-4E84-8E60-F11DB97C5CC7}', SHGVSPB_FOLDERNODEFAULTS, IPropertyBag, Bag));
try
if AAscending then Direction := SORT_ASCENDING
else Direction := DWORD(SORT_DESCENDING);
OleCheck(Bag.Write('GroupByDirection', Direction));
OleCheck(Bag.Write('GroupByKey:FMTID', GUIDToString(AColumn.fmtid)));
OleCheck(Bag.Write('GroupByKey:PID', AColumn.pid));
OleCheck(Bag.Write('GroupView', DWORD(-1)));
finally
Bag := nil;
end;
finally
CoTaskMemFree(IDList);
end;
finally
Desktop := nil;
end;
end;

Block Keyboard input completely

Is there any way to block the Keyboard input completely ? This should also block key combos like WIN+E.
I found this Code, is there anyway to change it to block only keyboard input (Mouse needs to work)
procedure TForm1.Button1Click(Sender: TObject) ;
function FuncAvail(dllName, funcName: string; var p: pointer): boolean;
var
lib: THandle;
begin
result := false;
p := nil;
if LoadLibrary(PChar(dllName)) = 0 then exit;
lib := GetModuleHandle(PChar(dllName)) ;
if lib <> 0 then
begin
p := GetProcAddress(lib, PChar(funcName)) ;
if p <> nil then Result := true;
end;
end;
var
BlockInput : function(Block: BOOL): BOOL; stdcall;
begin
if FuncAvail('USER32.DLL', 'BlockInput', #BlockInput) then
begin
ShowMessage('Your Mouse and Keyboard will be blocked for 5 seconds!') ;
BlockInput(true) ;
Sleep(5000) ;
BlockInput(false) ;
end;
end;
end.
Would this code also work with WIN keys etc ?
Thanks!
You're thinking way too hard.
The appropriate way to set up a kiosk that can be controlled by the mouse and not the keyboard is to not have a keyboard attached. (This also makes it impossible for an unscrupulous kiosk-user to steal your keyboard.)
This also means that, if you need to perform administrative tasks, you can attach a keyboard (or remote in) and everything will work fine.
If for some reason removing the keyboard is not a feasible option, there is an unsupported way of doing this in software: remove the UpperFilters value from
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE10318}
This disables input from all normal keyboard devices, but the Remote Desktop virtual keyboard will still work, so you may want to ensure that Remote Desktop is configured and working first.
For your reference, should you want to reverse the process, UpperFilters is normally a REG_MULTI_SZ containing a single string "kbdclass" (without the quote marks).

Tracking changes made to a folder in Delphi

I need to writing a Delphi program which will monitor a folder for changes (add, update, rename and removal of files).
I have seen suggestions to use theTShellChangeNotifier. Is this the correct solution for this problem? How should I use it?
This question might help. mghie's answer shows how to properly use ReadDirectoryChangesW.
I think this article will help you: Monitoring System Shell Changes using Delphi
Basically it analyzes the TShellChangeNotifier, discards it and then goes for a TSHChangeNotify which is basically a wrapper for the SHChangeNotify windows api function.
i suggest using madShell
RegisterShellEvent(ShellEvent, pathToMonitor, false, [seItemCreated, seItemRenamed]);
//
procedure Tform.ShellEvent(event: TShellEventType; const obj1, obj2: IShellObj; drive: char; value: cardinal);
var
filename: string;
isReady: boolean;
begin
if (event = seItemCreated) then
filename := obj1.Path
else if (event = seItemRenamed) then
filename := obj2.Path
else
exit;
// try to open to ensure it's read for reading
repeat
try
TfileStream.Create(filename, fmOpenRead + fmShareExclusive).Free;
isReady := true;
except
isReady := false;
sleep(250);
end;
until (isReady) or (not FileExists(filename));
OutputDebugString(pChar('ShellEvent: ' + filename));
end;

Controlling where (x,y) of a newly opened window in Delphi 2006

I'm trying to control the coordinates of where my program opens a new window because currently they're opening ontop of each other. Does anyone have a working example of how to do this?
You can always set the .Top and .Left properties manually, like this:
procedure TForm1.Button1Click(Sender: TObject);
var
frm : TForm;
begin
frm := TForm.Create(Self);
frm.Left := 100; //replace with some integer variable
frm.Top := 100; //replace with some integer variable
frm.Show;
end;
However, Windows has a default window placement algorithm that tries to keep the title bars of each window visible. On my computer, repeated clicks to this Button1 procedure give nicely stacked windows:
procedure TForm1.Button1Click(Sender: TObject);
var
frm : TForm;
begin
frm := TForm.Create(Self);
frm.Show;
end;
Also, don't forget that you can use the built-in set of TPosition locations:
procedure TForm1.Button1Click(Sender: TObject);
var
frm : TForm;
begin
frm := TForm.Create(Self);
frm.Position := poOwnerFormCenter;
{
Other possible values:
TPosition = (poDesigned, poDefault, poDefaultPosOnly, poDefaultSizeOnly,
poScreenCenter, poDesktopCenter, poMainFormCenter, poOwnerFormCenter);
//}
frm.Show;
end;
This type of functionality has been explained for C# in another question on SO.
Also, for Delphi, check out Understanding and Using Windows Callback Functions in Delphi which describes getting handles for windows that are currently open. And see Shake a window (form) from Delphi code which describes how to move a window once you've got its handle.

Resources