Recent

Author Topic: Problem porting ScintEdit  (Read 7987 times)

typo

  • Hero Member
  • *****
  • Posts: 3051
Problem porting ScintEdit
« on: November 02, 2014, 01:26:48 pm »
I see some similar questions, but not a solution. Anyone knows how to solve the problem wich appears on this procedure of TScintEdit:

Code: [Select]
procedure TScintEdit.CreateWnd;
begin
  inherited;
  FDirectPtr := Pointer(SendMessage(Handle, SCI_GETDIRECTPOINTER, 0, 0));
  if FDirectPtr = nil then
    Error('CreateWnd: FDirectPtr is nil');
  UpdateCodePage;
  Call(SCI_SETCARETPERIOD, GetCaretBlinkTime, 0);
  Call(SCI_SETSCROLLWIDTHTRACKING, 1, 0);
  { The default popup menu conflicts with the VCL's PopupMenu on Delphi 3 }
  Call(SCI_USEPOPUP, 0, 0);
{$IFNDEF UNICODE}
  { This hack is needed because non-Unicode VCL replaces the Scintilla's
    default Unicode window proc with an ANSI one }
  if Win32Platform = VER_PLATFORM_WIN32_NT then
    Call(SCI_SETKEYSUNICODE, 1, 0);
{$ENDIF}
  ApplyOptions;
  UpdateStyleAttributes;
  if FAcceptDroppedFiles then
    DragAcceptFiles(Handle, True);
end;       

The problem is with FDirectPtr  in the line:

Code: [Select]
FDirectPtr := Pointer(SendMessage(Handle, SCI_GETDIRECTPOINTER, 0, 0));

which is nil after calling SendMessage.

Thanks.
« Last Edit: November 02, 2014, 01:28:22 pm by typo »

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7498
Re: Problem porting ScintEdit
« Reply #1 on: November 02, 2014, 01:33:16 pm »
I know nothing about scintilla, but maybe Windows vs LCL  Sendmessage? Delphi doesn't have the difference (and I'm not even 100%sure Lazarus does on Windows), but to test you could prefix it with windows. if you want to force a real windows message.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Problem porting ScintEdit
« Reply #2 on: November 02, 2014, 02:03:48 pm »
Prefixed, but not solved.

Thanks.

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Problem porting ScintEdit
« Reply #3 on: November 02, 2014, 04:02:12 pm »
Check that you are sending the message to a valid window "handle". Maybe with IsWindow(Handle)

Edit:
I assume you are referring to this. According to its source code:

scintilla225\scintilla\win32\ScintillaWin.cxx

Code: [Select]
sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
try {
//Platform::DebugPrintf("S M:%x WP:%x L:%x\n", iMessage, wParam, lParam);
iMessage = SciMessageFromEM(iMessage);
switch (iMessage) {
...
case SCI_GETDIRECTPOINTER:
return reinterpret_cast<sptr_t>(this);
...
« Last Edit: November 02, 2014, 04:11:19 pm by engkin »

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Problem porting ScintEdit
« Reply #4 on: November 02, 2014, 04:26:23 pm »
No, I am referring to this:

https://github.com/jrsoftware/issrc/blob/master/Components/ScintEdit.pas

The window handle is valid.
« Last Edit: November 02, 2014, 04:36:11 pm by typo »

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Problem porting ScintEdit
« Reply #5 on: November 02, 2014, 05:10:55 pm »
CreateSubClass is not implemented, yet. It is needed for TScintEdit.CreateParams. That's why SendMessage(Handle, SCI_GETDIRECTPOINTER ... returns 0.

For Windows, I believe you can use SetWindowLong with GWL_WNDPROC to do the same.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Problem porting ScintEdit
« Reply #6 on: November 02, 2014, 05:13:05 pm »
CreateSubClass is needed for TScintilla, but not for TScintEdit.

https://github.com/borneq/ScintWrapper/commit/6d0d6e57fc7d0c91f35a3f8e47300667aa8e6a75

Code: [Select]
procedure TScintilla.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  CreateSubClass(Params, 'SCINTILLA');
end;
« Last Edit: November 02, 2014, 05:25:35 pm by typo »

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Problem porting ScintEdit
« Reply #7 on: November 02, 2014, 05:28:37 pm »
CreateSubClass is needed for TScintilla, but not for TScintEdit.

It is needed for TScintEdit as well. The code in your very first post shows:
Code: [Select]
procedure TScintEdit.CreateWnd;
begin
  inherited; //<------

follow this inherited call to:
Code: [Select]
procedure TWinControl.CreateWnd;
..
      CreateParams(Params);
..

which calls:
Code: [Select]
procedure TScintEdit.CreateParams(var Params: TCreateParams);
begin
  inherited;
  CreateSubClass(Params, 'Scintilla'); //<----
...

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Problem porting ScintEdit
« Reply #8 on: November 02, 2014, 05:40:23 pm »
Well, the problem may be that, indeed.

Do you know in which unit of Delphi is declared CreateParams?

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Problem porting ScintEdit
« Reply #9 on: November 02, 2014, 05:46:25 pm »
Why do you need that. I assume it should be in the same unit where TWinControl is declared as it is a member method of its class. Beware that nothing from Delphi's source can be copied over to FPC/Lazarus.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Problem porting ScintEdit
« Reply #10 on: November 02, 2014, 08:06:30 pm »
If I don't publish it, I guess I don't violate copyright. I will not use it in any application as well, I am only testing.

http://bugs.freepascal.org/view.php?id=26989

Well, my TWinControl.CreateSubClass procedure is now working fine and I have a new error with "ComponentName has no parent window".

Thanks.
« Last Edit: November 02, 2014, 08:27:18 pm by typo »

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Problem porting ScintEdit
« Reply #11 on: November 03, 2014, 10:55:30 am »
Now I apparently solved the previous problem about No Parent Window with this:

Code: [Select]
procedure TScintEdit.CreateParams(var Params: TCreateParams);
begin
  inherited;
  CreateSubClass(Params, 'Scintilla');
  Params.ExStyle := Params.ExStyle or WS_EX_CLIENTEDGE;
  Params.WindowClass.style := Params.WindowClass.style and
    not (CS_HREDRAW or CS_VREDRAW);

  Params.WndParent := Parent.Handle;  // <<<<<<
end;     

but have an Access Violation when I put the component on the form.
« Last Edit: November 03, 2014, 10:59:11 am by typo »

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Problem porting ScintEdit
« Reply #12 on: November 03, 2014, 11:32:05 am »
On a new form I put the following code in a button's event:
Code: [Select]
procedure TForm1.Button3Click(Sender: TObject);
var
  hmod: THandle;
  hwndScintilla: HWnd;
begin

  //hmod := LoadLibrary('SciLexer.DLL');
  hmod := LoadLibrary('isscint.dll');

  if (hmod=0) then
  begin
    MessageBox(Handle,
    'The Scintilla DLL could not be loaded.',
    'Error loading Scintilla',
    MB_OK or MB_ICONERROR);
  end;

  hwndScintilla := CreateWindowEx(0,
  'Scintilla','', WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_CLIPCHILDREN,
  10,10,500,400,handle,0, hInstance,nil);
end;
and it worked.

Then simply moved CreateWindowEx part to:
Code: [Select]
procedure TScintEdit.CreateWnd;
begin
  //inherited;

  Handle := CreateWindowEx(0,
  'Scintilla','', WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_CLIPCHILDREN,
  10,10,500,400,Parent.Handle,0, hInstance,nil);

  FDirectPtr := Pointer(SendMessage(Handle, SCI_GETDIRECTPOINTER, 0, 0));
  if FDirectPtr = nil then
    Error('CreateWnd: FDirectPtr is nil');

{
...
}
end;
Notice that I commented everything else out. This way I don't need to subclass anything. Does it work for you?

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Problem porting ScintEdit
« Reply #13 on: November 03, 2014, 11:46:10 am »
Yes, this works for me.

I don't know Scintilla, now I have a black window on my form.

engkin

  • Hero Member
  • *****
  • Posts: 2513
Re: Problem porting ScintEdit
« Reply #14 on: November 03, 2014, 11:53:24 am »
I believe the black window is due to wrong options in UpdateStyleAttributes. Comment that call out, and it turns into a nice white window with a cursor. Of course it needs correct options.