Jump to content

ChrisChuah

Members
  • Content Count

    121
  • Joined

  • Last visited

Everything posted by ChrisChuah

  1. ChrisChuah

    DBGrid sort descending on Column Title Click

    hi Thanks. I will use the AddIndex function to do the sorting. regards chris
  2. Hi I am using TSQLQuery, TClientDataSet and TDataSetProvider with DBGrid I will click on the record row in the middle of the grid and the grid shows that it is highlighted HOwever, when i close and open the ClientDataSet to refresh the data, i would use the bookmark to go back to the last bookmark before the Client dataset is Close l_bookmark := TntDBGrid1.Datasource.DataSet.GetBookmark; TntDBGrid1.DataSource.DataSet.Close; TntDBGrid1.DataSource.Dataset.Open; TntDBGrid1.DataSource.DataSet.GotoBookmark(l_bookmark); TntDBGrid1.DataSource.Dataset.FreeBookmark(l_bookmark); After open, the indicator is shown correctly on the dbgrid but the highlighted row is on the first row. see pic please advise regards chris
  3. Hi I am not sure if this function affected the drawing procedure TForm1.ClientDataSet1AfterOpen(DataSet: TDataSet); var l_index : integer; l_fieldName : string; begin for l_index := 0 to ClientDataSet1.FieldCount - 1 do begin l_fieldName := ClientDataSet1.Fields[l_index].FieldName; ClientDataSet1.Fields[l_index].DisplayWidth :=10; if (l_fieldName = 'SDT') or (l_fieldName = 'EST_D') or (l_fieldName = 'LAST_D') or (l_fieldName = 'ACT_D') or (l_fieldName = 'CREATED_AT') or (l_fieldName = 'UPDATED_AT') then ClientDataSet1.Fields[l_index].OnGetText := getDateTimeStr else if (l_fieldName = 'STIME') then ClientDataSet1.Fields[l_index].OnGetText := getTimeStr else if (l_fieldName = 'SDATE') then ClientDataSet1.Fields[l_index].OnGetText := getDateStr else if (l_fieldName = 'ORDEST_N_C') or (l_fieldName = 'FREE_REM') then ClientDataSet1.Fields[l_index].OnGetText := getForeignStr; end; Dataset.Last; end; procedure TForm1.TntDBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); var l_bitmap : TBitmap; l_rect : TRect; l_bmpWidth, l_width : integer; l_str : string; begin if (ClientDataSet1.RecNo mod 2 = 0) then begin if TntDBGrid1.Canvas.Brush.Color = TntDBGrid1.Color then begin TntDBGrid1.Canvas.Brush.Color := clSkyBlue; end; end; l_rect := Rect; l_str := Column.Field.DisplayText; if Column.FieldName = 'ROW_ID' then begin l_bitmap := TBitmap.create; try ImageList3.GetBitmap(1, l_bitmap); l_bmpWidth := (Rect.bottom - Rect.Top); l_rect.Right := Rect.Left + l_bmpWidth; TntDBGrid1.Canvas.StretchDraw(l_rect, l_bitmap); finally l_bitmap.Free; end; // cc : reset the output rectangle l_rect := Rect; l_rect.Left := l_rect.Left + l_bmpWidth; l_width := 5 + TntDBGrid1.Canvas.TextExtent(l_str).cx; <== if (l_width > Column.Width) then <== Column.Width := l_width; <== end; TntDBGrid1.DefaultDrawColumnCell(l_rect, DataCol, (Column as TTntColumn), State); end; As i store all the dates as Unix Epoch format. hence i need to translate all the values to date time format when drawn on the grid. However, is there a way to know when the drawing on the grid is completed? Or is there a better way to make the grid draw out faster? Seems like if i dont make it auto size for every column, the drawing is faster. The longest column is the Foreign Characters and the resizing took quite long there Is there a way to auto size and auto fit the column which is not done during the drawing part? please advise regards chris
  4. I just found out that i can use the dataset to refresh rather than Open and close. The dbgrid will refresh with updated content. Now i have another problem is when i open the dataset, the dbgrid is filled to the bottom and it will somehow stop there.. i need to scroll down to request it to draw again. anyone have this problem? is there a way to scroll all the way down the grid automatically once the drawing is completed? please see this video on the problem.. anyone can advise? source procedure TfrmMain.dbgABNDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); var l_bitmap : TBitmap; l_rect : TRect; l_bmpWidth, l_width : integer; l_str : string; begin if ( (dbgABN.DataSource.Dataset as TClientDataset).RecNo mod 2 = 0) then begin if dbgABN.Canvas.Brush.Color = dbgABN.Color then begin dbgABN.Canvas.Brush.Color := clSkyBlue; end; end; l_rect := Rect; l_str := Column.Field.DisplayText; if Column.FieldName = 'ROW_ID' then begin l_bitmap := TBitmap.create; try ImageList2.GetBitmap(0, l_bitmap); l_bmpWidth := (Rect.bottom - Rect.Top); l_rect.Right := Rect.Left + l_bmpWidth; dbgABN.Canvas.StretchDraw(l_rect, l_bitmap); finally l_bitmap.Free; end; // cc : reset the output rectangle l_rect := Rect; l_rect.Left := l_rect.Left + l_bmpWidth; end; l_width := 5 + dbgABN.Canvas.TextExtent(l_str).cx; if (l_width > Column.Width) then Column.Width := l_width; dbgABN.DefaultDrawColumnCell(l_rect, DataCol, (Column as TTntColumn), State); end; Screen_Recording_2022-06-30_at_9_50.33_AM.mp4
  5. Thank you. Seems like i did not see that bookmarks are invalidated when dataset is closed and opened again. Then how can i refresh the dataset if i do not close and open it?
  6. ChrisChuah

    DBGrid sort descending on Column Title Click

    Thank you for your help
  7. Hi Is there a link to download Indy as well as installation manual for Lazarus running on Ubuntu X86_64? please advise regards chris
  8. ChrisChuah

    Indy download and installation on Lazarus running on Ubuntu

    thank you justin Will try it out on lazarus
  9. ChrisChuah

    TEdit Text cannot align vertical centered

    Hi For the TLabel, i can align the text vertically centre using the Layout properties. However, for TEdit, there isnt any option for this. Please help on how i can have the TEdit text aligned vertically centered. regards chris
  10. ChrisChuah

    TEdit Text cannot align vertical centered

    thanks remy Its working now. not sure why i could not connect to that link when i was in office thanks chris
  11. ChrisChuah

    TEdit Text cannot align vertical centered

    Hi Thank you. That link does not work. Just have to stick to the underlying windows control. regards chris
  12. Hi Each time i send a packet of data to the broadcast address, the same packet will be received back again. How can i 1. control the idUDPClient to ignore the packet 2. How to determine the ip address is a broadcast address in the network please advise regards chris
  13. Hi On my mac, it seems that i have many network interfaces. I used Indy GStack.GetLocalAddressList to obtain all these interface name and IP address. Stack Local Address 0: en0: FE80:0:0:0:102B:BAE3:A50E:FEDA Stack Local Address 1: en0: 192.168.1.10 Stack Local Address 2: en1: FE80:0:0:0:C55:FF1F:977A:4ECD Stack Local Address 3: en1: 192.168.1.11 Stack Local Address 4: awdl0: FE80:0:0:0:380D:36FF:FE0A:D127 Stack Local Address 5: llw0: FE80:0:0:0:380D:36FF:FE0A:D127 Stack Local Address 6: utun0: FE80:0:0:0:FE2C:6391:70B1:32E5 Stack Local Address 7: utun1: FE80:0:0:0:D512:288C:E8D7:52E1 Stack Local Address 8: utun2: FE80:0:0:0:CE81:B1C:BD2C:69E Stack Local Address 9: bridge100: 172.16.90.1 Stack Local Address 10: bridge100: FE80:0:0:0:787B:8AFF:FE3C:7864 Stack Local Address 11: bridge101: 192.168.83.1 Stack Local Address 12: bridge101: FE80:0:0:0:787B:8AFF:FE3C:7865 Stack Local Address 13: bridge102: 192.168.84.1 Stack Local Address 14: bridge102: FE80:0:0:0:787B:8AFF:FE3C:7866 Stack Local Address 15: bridge103: 192.168.85.1 Stack Local Address 16: bridge103: FE80:0:0:0:787B:8AFF:FE3C:7867 Stack Local Address 17: bridge104: 172.16.49.1 Stack Local Address 18: bridge104: FE80:0:0:0:787B:8AFF:FE3C:7868 If i want to send a broadcast packet onto 192.168.84.255 (Bridge102), How can i specify it in idUDPClient? Or will idUDPClient able to automatically send it out via that interface? Please advise regards chris
  14. ChrisChuah

    How to use a particular network interface to send out UDP data

    Thanks Remy I will try to use the BoundIP property on my testing. regards chris
  15. Hi Remy Yes. As i send a UDP packet to a 192.168.100.255, the IP address that returns to me is also 192.168.100.255 as well as a reply from other servers. Is there a function to say isBroadcastAddress(aIPAddress: string) that i can use so as to know its a broadcast address? Does Indy library has such function? regards chris
  16. ChrisChuah

    Access Violation when i free idUDPClient

    Hi I am trying to create a thread that will send out UDP message and when it receive the UDP message from the server, it will send a Reply as event back to the caller. I create the UDPClient in the Execute function and of course i would need to free it when the thread ends. But why do i get access violation when i free it? The call stack is --IdSocketHandle.CloseSocket. --IdSocketHandle.Destroy -- System.TObject.free; --IdUDPBase.CloseBinding --IdUDPBase.Destroy --IdUDPClient.Destroy -- System.TObject.Free --FUDP.Free; please help to guide me what is the best way to send out UDP message and wait for reply? Should i use UDPServer rather than UDPClient? === Code === procedure ilUDPClientThd.Execute; var l_port : UInt32; l_memStream : TMemoryStream; l_len : integer; l_buf : TIdBytes; l_ilUDPData : Tt_BootReqMsg; l_ip : string; l_ipBytes : array[0..15] of byte; FUDP: TIdUDPClient; begin { Place thread code here } l_ip := getOwnIP; if l_ip = '' then begin DoOnLog('Cannot find own IP address'); exit; end; FUDP := TIdUDPClient.Create(nil); FUDP.Host := FBroadcastIP; FUDP.Port := FBroadcastPort; // FUDP.Binding.Port := FBroadcastPort; try l_port := FBroadcastPort; l_memStream := TMemoryStream.create; l_buf := ToBytes('SOREQ', IndyTextEncoding_ASCII); l_memStream.Write(l_buf[0], 6); l_port := GStack.HostToNetwork(l_port); l_memStream.write(l_port, 4); getArrayBytes(l_ip, l_ipBytes); l_memStream.Write(l_ipBytes, SizeOf(l_ipBytes)); l_len := l_memStream.size; setLength(l_buf, l_len); l_memStream.position := 0; l_memStream.Read(l_buf[0], l_len ); l_memStream.Clear; try FUDP.ReceiveTimeout := 3000; FUDP.BroadcastEnabled := true; // FUDP.Active := true; FUDP.SendBuffer(l_buf); // FUDP.SendBuffer(l_buf[0], l_len); FMsg := 'Send To Address: ' + FUDP.Host + ' Port: ' + Inttostr(FUDP.Port) + ' using IP: ' + l_ip; Synchronize(WriteToLog); // l_len := FUDP.ReceiveBuffer(l_ilUDPData, sizeof(l_ilUDPData), FUDP.ReceiveTimeout); setLength(l_buf, sizeof(l_ilUDPData)); l_len := FUDP.ReceiveBuffer(l_buf); if l_len <= 0 then begin FMsg:='No Data received in UDP'; FRepliedClientIP := ''; FRepliedClientPort := 0; Synchronize(ReplyToClient); Synchronize(WriteToLog); end else begin l_ilUDPData.Port := GStack.NetworkToHost(l_ilUDPData.Port); FRepliedClientIP := getStringFromBytes(l_ilUDPData.hid); FRepliedClientPort := l_ilUDPData.port; Synchronize(ReplyToClient); end; except on E:Exception do begin FMsg := 'Error in Recv Data in UDP: ' + e.message; FRepliedClientIP := ''; FRepliedClientPort := 0; Synchronize(ReplyToClient); Synchronize(WriteToLog); end; end; l_memStream.Free; FUDP.Binding.Destroy; except on E:exception do begin FMsg := 'Exception in SoFind: ' + e.Message; FRepliedClientIP := ''; FRepliedClientPort := 0; Synchronize(ReplyToClient); Synchronize(WriteToLog); end; end; FUDP.Disconnect; FUDP.Free; <<==== Access violation when i tried to free UDP Client end;
  17. ChrisChuah

    Access Violation when i free idUDPClient

    Thanks Remy.
  18. Hi I have an existing component that communicates with a server via TCP. However, this component can only be used in delphi. When i call a function in this component, it will send out a TCP message. After some time, it will return back data and it will trigger an event back in the component. So, anytime i want to use this component, i can drop the component into the form. I can double click on the event and write codes to handle the result from the event. Now, if i want to make this component into a DLL for C sharp programmer to use How can i create events into the dll for C Sharp programmer to use? Is there any example that i can use or follow please help regards chris
  19. ChrisChuah

    Access Violation when i free idUDPClient

    Hi When i use the IdUDPClient inside the thread object, the idUDPClient does not get any messages back even though it can be seen from the Wireshark that the message was sent back. However, if i place the IdUDPClient on a Form, i am able to get the message. Something funny is that when i use the IdUDPClient on the Form to send out the message, the first response message header is SOREQ <== this header is request header Checking on the Wireshark, the server returned SORE I tried to initialise the l_buf to $0 before retrieving from idUDPClient. However, its only the first message sent that will be always SOREQ and the rest will be SORE And the IP address returned in the message should be 192.168.84.128 which indicate the server address itself. seems like the first message is the same message that i sent out. please advise regards chris ===== Code for IdUDPClient on Form ===== procedure TForm1.Button2Click(Sender: TObject); var l_port : UInt32; l_memStream : TMemoryStream; l_len : integer; l_buf, l_buf1 : TIdBytes; l_ilUDPData : Tt_BootReqMsg; l_ip : string; l_ipBytes : array[0..15] of byte; FMsg : string; FRepliedClientIP : string; FRepliedClientPort : Uint32; l_index : integer; begin l_ip := getOwnIP; if l_ip = '' then begin writeLog('Cannot find own IP address'); exit; end; IdUDPClient1.Host := '192.168.84.255'; IdUDPClient1.Port := 55510; IdUDPClient1.BoundPort := 55510; try // FUDP.Active := true; l_memStream := TMemoryStream.create; l_buf := ToBytes('SOREQ'#0, IndyTextEncoding_ASCII); l_memStream.Write(l_buf[0], 6); l_port := 55510; l_port := GStack.HostToNetwork(l_port); l_memStream.write(l_port, 4); getArrayBytes(l_ip, l_ipBytes); l_memStream.Write(l_ipBytes, SizeOf(l_ipBytes)); l_len := l_memStream.size; setLength(l_buf, l_len); l_memStream.position := 0; l_memStream.Read(l_buf[0], l_len ); l_memStream.Clear; try IdUDPClient1.ReceiveTimeout := 3000; IdUDPClient1.BroadcastEnabled := true; IdUDPClient1.SendBuffer(l_buf); FMsg := 'Send To Address: ' + IdUDPClient1.Host + ' Port: ' + Inttostr(IdUDPClient1.Port) + ' using IP: ' + l_ip; WriteLog(FMsg); setLength(l_buf, sizeOf(l_ilUDPData)); for l_index := 0 to length(l_buf) - 1 do. <== initialise the buffer but i still receive SOREQ only on 1st time. l_buf[l_index] := byte($0); l_len := IdUDPClient1.ReceiveBuffer(l_buf, 2000); if l_len <= 0 then begin FMsg:='No Data received in UDP'; FRepliedClientIP := ''; FRepliedClientPort := 0; WriteLog(FMsg); end else begin l_memStream.Clear; l_memStream.Position := 0; l_memStream.Write(l_buf[0], l_len); l_memStream.Position := 0; setlength(l_buf1, 6); l_memStream.Read(l_buf1[0], length(l_buf1)); WriteLog('Op Code: ' + getStringFromBytes(l_buf1)); l_memStream.Read(FRepliedClientPort, sizeof(FRepliedClientPort)); WriteLog('Port value: ' + Inttostr(FRepliedClientPort)); l_memStream.Read(l_ilUDPData.hid, sizeof(l_ilUDPData.hid)); FRepliedClientIP := getStringFromBytes(l_ilUDPData.hid); FRepliedClientPort := GStack.NetworkToHost(FRepliedClientPort); WriteLog('Replied. IP: ' + FRepliedClientIP + ' Port: ' + Inttostr(FRepliedClientPort)); end; except on E:Exception do begin FMsg := 'Error in Recv Data in UDP: ' + e.message; FRepliedClientIP := ''; FRepliedClientPort := 0; WriteLog(FMsg); end; end; l_memStream.Free; except on E:exception do begin FMsg := 'Exception in SoFind: ' + e.Message; FRepliedClientIP := ''; FRepliedClientPort := 0; WriteLog(FMsg); end; end; end; ==== End =====
  20. ChrisChuah

    Access Violation when i free idUDPClient

    Hi Remy Would like to ask why the UDPClient did not receive any data. Attached is the screen capture of the Wireshark. The first pic shows the server received the message sent from the delphi client The second pic shows the server sends out the SORE (response) message to the delphi client IP address. However, the client reported that there is no data received <27/5/2022 11:14:02 am> Send To Address: 192.168.84.255 Port: 55510 using IP: 192.168.84.129 <27/5/2022 11:14:05 am> IP: Port: 0 replied <27/5/2022 11:14:05 am> No Data received in UDP Did i do something not right? please advise regards chris
  21. ChrisChuah

    Access Violation when i free idUDPClient

    Thanks Remy The only problem that i have with strings in delphi is that I dont know if they are Windows widechar or UTF8 char or ansi value Edit1.text := 'MET'; ShowMe(Edit1.text); Function showMe(aValue : string); var l_value : string; begin l_value := aValue + 'A'; UDPClient.Write(l_value); end; So when the edit1 value is pass into ShowMe function, what is the length of l_value? As my server only accepts ANSI type of characters, the data sent may be Windows WideChar. Hence to be on the safe side, i would have to translate it to idBytes. What is the general rule on how you would send data when the server only accepts ANSI characters. Please advise regards chris BTW, After 20 years of using Delphi, i still remembered you were helping me last time when i was using Delphi 5, 6 in one of the forum. Now, its hard to find help for delphi.
  22. thank you very much for your advices. Guess i think i will try to use COM dll and see if C sharp can use it or not.
  23. Hi So sorry it seems like its calling DLL rather than using Delphi to create DLL isnt it? Its been a long time since i create a DLL but isnt there an export function or something like that? regards chris
  24. Hi Actually I want to use delphi to create a DLL with functions or procedures containing a callback. How can i create such functions in delphi so that the project can be compiled to a dll for C Sharp programmer to use Previously all DLL functions does not have function pointer or callback functions when i was using Delphi 6 era. Also my C sharp programmers said they cannot use COM because their program will be running in Docker for linux please advise regards chris
  25. Hi, is there such components for delphi to develop iOS and Android application to read the MRZ (Machine Readable Zone) and the NFC chip on passport based on MRTD (Machine Readable Travel Document) on passport? regards chris
×