GetConsoleTitle with pchar as argument ? lazarus / 67-Windows ---------------------------------------------------------------------- Nitorami · 2023-03-10 08:29 GetConsoleTitle works with a shortstring as parameter but not with a pchar. Why ? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$H-}uses windows; var s: shortstring;    p: pchar;begin  writeln;  s :=  '##### #####################################################################' ;  writeln ('GetTitle returns ',GetConsoleTitle (@s[1],50));  //works  writeln (s+LineEnding);   p :=  '##################################### #####################################';  writeln ('GetTitle returns ',GetConsoleTitle (p,50));      //doesn't work  writeln (p+LineEnding);  writeln ('GetTitle returns ',GetConsoleTitle (@p[0],50));  //doesn't either  writeln (p+LineEnding);end.   Output: Running "c:\temp\getconsoletitle.exe " GetTitle returns 24 Eingabeaufforderung - fp ################################################# GetTitle returns 0 ###################################################################### #### GetTitle returns 0 ###################################################################### #### ---------------------------------------------------------------------- Red_prig · 2023-03-10 09:08 Because pchar is a reference to data, first allocate the memory and put the reference in p, then when the data is no longer needed, free it accordingly ---------------------------------------------------------------------- Nitorami · 2023-03-10 09:10 Understood, but I initialised p with p := '####....', so it must have been allocated at a speciifc address ? ---------------------------------------------------------------------- Red_prig · 2023-03-10 09:11 '####....' is a constant and is write-protected ---------------------------------------------------------------------- Nitorami · 2023-03-10 09:31 You mean the content of pchar is stored in a specific write-protected area of memory which the API function cannot write to ? ---------------------------------------------------------------------- Red_prig · 2023-03-10 09:46 correct ---------------------------------------------------------------------- JuhaManninen · 2023-03-10 12:44 Yes, memory must be allocated for PChar with StrAlloc(). Later it should be freed with StrDispose(). ShortString is a good type if the Title does not exceed 255 characters. AnsiString can be used, but you must set its length first. After that it is freed automatically. ---------------------------------------------------------------------- Nitorami · 2023-03-10 13:57 Thank you, that enlightens me. Maybe you can help me a bit further. I try to copy text to the windows clipboard from within a Console. I got it working in principle: First, get a window handle to the Console via GetConsoleTitle and FindWindow().Using this handle, I can now OpenClipBoard() and EmptyClipBoard().Then, use GlobalAlloc to reserve a memory region; it returns a handle, not a pointer. I can pass this handle to SetClipboardData() to copy the associated memory to the clipboard.But to get something into this memory first, I need its address. I can get a pointer via GlobalLock (handle), and can now move() my own memory content (e.g. the string) to this memory. This seems to work, but I wonder if I could avoid the extra memory allocation via Global Alloc. I would need a memory handle for my own Pascal structure but cannot see a way how to do this.[/list] ---------------------------------------------------------------------- JuhaManninen · 2023-03-10 14:44 I can only recommend the LCL unit Clipbrd and class TClipboard. I don't use Windows myself and don't know much about WinAPI programming. LCL pulls in a lot of code, thus in your console program you may want to avoid it. If one GlobalAlloc is all you need for the task, it sounds like a reasonable addition. ---------------------------------------------------------------------- Nitorami · 2023-03-10 14:56 Agreed it would be easier via Lazarus and the LCL. But I still use the textmode IDE because compliation speed is unsurpassed (unless the windows virusscanner intervenes). I often write small throw-away programs during my work, and the Strg-F9 button starts to wear out... Can I use the LCL from within a Console program ? Rather not, I guess ? ---------------------------------------------------------------------- JuhaManninen · 2023-03-11 07:54 Quote from: Nitorami on March 10, 2023, 03:56:47 pmCan I use the LCL from within a Console program ? Rather not, I guess ? You can but it may be difficult without the Lazarus IDE. LCL has a "NoGUI" widgetset which does not call any real widgetset. For example the LazBuild console program uses it. The same LazBuild can compile and build projects made with Lazarus. You could modify such a project with a textmode IDE and then run LazBuild. Compilation would not be super-fast any more because LCL pulls in lots of code. ---------------------------------------------------------------------- Raskaton · 2023-07-03 18:16 Last time I use this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses  SysUtils;var  s: ShortString;  buf, p: PChar;  len: integer;begin  buf := StrAlloc(250); //temp buffer  len := GetConsoleTitle(buf,250);  //if len=0 then {Alloc to 'buf' more and repeat Get}   p := StrAlloc(len);  //alloc real size  p := StrLCopy(p, buf, len); //get real data  StrDispose(buf);  //free buffer   s := StrPas(p);   WriteLn('Title = ', p); //automatic typecast will be done Alloc, StrPas and Dispose by ref  WriteLn('Len = ', StrLen(p));  //#0 not included  StrDispose(p);   WriteLn('Title = ', s);  WriteLn('Len = ', Length(s));end; PS not tested ---------------------------------------------------------------------- ASerge · 2023-07-03 19:55 Quote from: Raskaton on July 03, 2023, 08:16:05 pmPS not tested Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$MODE OBJFPC}{$APPTYPE CONSOLE} uses Windows; var  Dummy: UnicodeChar;  Count: DWORD;  U: UnicodeString;begin  // GetConsoleTitleW expects the size in bytes, not in chars, but returns in chars  // The documentation is incorrect about this  // The size cannot be zero  Count := GetConsoleTitleW(@Dummy, SizeOf(Dummy));  SetString(U, nil, Count);  GetConsoleTitleW(Pointer(U), (Count + 1) * SizeOf(UnicodeChar)); // + #0  Writeln(U);  Readln;end.Tested. ---------------------------------------------------------------------- KodeZwerg · 2023-07-04 07:23 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  Count: DWORD;  W: array[0..MAX_PATH -1] of WideChar;begin  Count := GetConsoleTitleW(@W, SizeOf(W));  W[Count] := #0;  Writeln(string(W));  Readln;end.or Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  W: array[0..MAX_PATH -1] of WideChar;begin  FillChar(W, SizeOf(W), #0);  GetConsoleTitleW(@W, SizeOf(W));  Writeln(string(W));  Readln;end.or Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$IF Defined(FPC) and Declared(FPC_VERSION) and (FPC_VERSION >= 3)}  {$DEFINE UniCode} { FreePascal UniCode support }{$IFEND} function GetConsoleOriginalTitleA(lpConsoleTitle: LPTSTR; nSize: DWORD): DWORD;  external 'kernel32.dll' name 'GetConsoleOriginalTitleA'; function GetConsoleOriginalTitleW(lpConsoleTitle: LPWSTR; nSize: DWORD): DWORD;  external 'kernel32.dll' name 'GetConsoleOriginalTitleW'; function GetConsoleOriginalTitle(lpConsoleTitle: {$IF Defined(UniCode)}LPWSTR{$ELSE}LPTSTR{$ENDIF}; nSize: DWORD): DWORD;  external 'kernel32.dll' name 'GetConsoleOriginalTitle' + {$IF Defined(UniCode)}'W'{$ELSE}'A'{$ENDIF}; var  W: array[0..MAX_PATH -1] of {$IF Defined(UniCode)}WideChar{$ELSE}AnsiChar{$ENDIF};begin  FillChar(W, Length(W) * SizeOf({$IF Defined(UniCode)}WideChar{$ELSE}AnsiChar{$ENDIF}), #0);  GetConsoleOriginalTitle(@W, SizeOf(W));  Writeln({$IF Defined(UniCode)}PWideChar{$ELSE}PAnsiChar{$ENDIF}(W));  Readln;end. ---------------------------------------------------------------------- KodeZwerg · 2023-07-04 10:40 Quote from: Nitorami on March 10, 2023, 02:57:21 pmThank you, that enlightens me. Maybe you can help me a bit further. I try to copy text to the windows clipboard from within a Console. I got it working in principle: First, get a window handle to the Console via GetConsoleTitle and FindWindow().Using this handle, I can now OpenClipBoard() and EmptyClipBoard().Then, use GlobalAlloc to reserve a memory region; it returns a handle, not a pointer. I can pass this handle to SetClipboardData() to copy the associated memory to the clipboard.But to get something into this memory first, I need its address. I can get a pointer via GlobalLock (handle), and can now move() my own memory content (e.g. the string) to this memory. This seems to work, but I wonder if I could avoid the extra memory allocation via Global Alloc. I would need a memory handle for my own Pascal structure but cannot see a way how to do this.[/list] This is how I would do. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; {$APPTYPE CONSOLE} uses  Windows, SysUtils; function GetTitle(Wnd: HWND): String;var lpch: String; len: DWORD;begin len := GetWindowTextLength(Wnd); SetLength(lpch, len); GetWindowText(Wnd, PChar(lpch), Length(lpch) + 1); Result := lpch;end; function GetClipboardText(Wnd: HWND; var Str: string): Boolean;var hData: HGlobal;begin Result:=True; if OpenClipboard(Wnd) then begin  try   hData:=GetClipboardData(CF_TEXT);   if hData<>0 then begin    try     SetString(Str, PChar(GlobalLock(hData)), GlobalSize(hData));    finally     GlobalUnlock(hData);    end;   end else Result:=False;   Str:=PChar(@Str[1]);  finally   CloseClipboard;  end; end else Result:=False;end; function SetClipboardText(Wnd: HWND; Value: string): Boolean;var hData: HGlobal; pData: pointer; Len: integer;begin Result:=True; if OpenClipboard(Wnd) then begin  try   Len:=Length(Value)+1;   hData:=GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Len);   try    pData:=GlobalLock(hData);    try     Move(PChar(Value)^, pData^, Len);     EmptyClipboard;     SetClipboardData(CF_Text, hData);    finally     GlobalUnlock(hData);    end;   except    GlobalFree(hData);    raise   end;  finally   CloseClipboard;  end; end else Result:=False;end; var  s, ss: string;  wnd: HWND;begin  wnd := GetForegroundWindow;  ss := GetTitle(wnd);  WriteLn('Window Caption: ', ss);  s := '';  if SetClipboardText(wnd, ss) then    begin      WriteLn('Copy to clipboard success.');      if GetClipboardText(wnd, s) then        begin          WriteLn('Text from clipboard: ', s);      end        else          WriteLn('Unabled to get text from clipboard.');    end    else      WriteLn('Copy to clipboard failed.');  ReadLn;end.I've missed a lot of pre-checkings, just a prototype to demonstrate. ---------------------------------------------------------------------- ASerge · 2023-07-04 18:45 Quote from: KodeZwerg on July 04, 2023, 09:23:32 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  Count: DWORD;  W: array[0..MAX_PATH -1] of WideChar;begin  Count := GetConsoleTitleW(@W, SizeOf(W));  W[Count] := #0;  Writeln(string(W));  Readln;end.Unsafe. If the title length is longer than the buffer "W[Count] := #0" will mess up the program stack.