unit sqlhelp;interfaceusesWinapi.Windows, System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.ExtCtrls,Vcl.Buttons, SynMemo, SynEditHighlighter, SynHighlighterURI, extra_controls,SynURIOpener, SynEdit, VirtualTrees, Vcl.Graphics,dbconnection, gnugettext, VirtualTrees.BaseTree, VirtualTrees.Types,VirtualTrees.BaseAncestorVCL, VirtualTrees.AncestorVCL, dbstructures;typeTfrmSQLhelp = class(TExtForm)URIOpenerDescription: TSynURIOpener;URIHighlighter: TSynURISyn;URIOpenerExample: TSynURIOpener;btnSearchOnline: TButton;ButtonClose: TButton;pnlMain: TPanel;pnlLeft: TPanel;treeTopics: TVirtualStringTree;editFilter: TButtonedEdit;pnlRight: TPanel;Splitter2: TSplitter;Splitter1: TSplitter;lblDescription: TLabel;lblKeyword: TLabel;memoDescription: TSynMemo;lblExample: TLabel;MemoExample: TSynMemo;timerSearch: TTimer;procedure FormCreate(Sender: TObject);procedure memosKeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);procedure ButtonOnlinehelpClick(Sender: TObject);procedure ButtonCloseClick(Sender: TObject);procedure DoSearch(Sender: TObject);procedure treeTopicsGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);procedure treeTopicsInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;var InitialStates: TVirtualNodeInitStates);procedure treeTopicsInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;var ChildCount: Cardinal);procedure treeTopicsGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex);procedure treeTopicsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);procedure treeTopicsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);procedure treeTopicsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;Column: TColumnIndex);procedure editFilterChange(Sender: TObject);procedure editFilterRightButtonClick(Sender: TObject);procedure FormClose(Sender: TObject; var Action: TCloseAction);procedure FormShow(Sender: TObject);private{ Private declarations }FConnection: TDBConnection;FKeyword: String;FRootTopics: TDBQuery;function GetHelpResult(Node: PVirtualNode): TDBQuery;procedure SetKeyword(Value: String);public{ Public declarations }property Keyword: String read FKeyword write SetKeyword;end;varSqlHelpDialog: TfrmSQLhelp; // global var, so we can apply settings via SetupSynEditorsconstDEFAULT_WINDOW_CAPTION : String = 'Integrated SQL-help' ;ICONINDEX_CATEGORY_CLOSED : Integer = 66;ICONINDEX_CATEGORY_OPENED : Integer = 67;ICONINDEX_HELPITEM : Integer = 68;implementationuses apphelpers, main;{$I const.inc}{$R *.dfm}procedure TfrmSQLhelp.FormCreate(Sender: TObject);begin// Set window-layoutlblKeyword.Font.Style := [fsBold];Caption := DEFAULT_WINDOW_CAPTION;FixVT(treeTopics);HasSizeGrip := True;treeTopics.Clear;FreeAndNil(FRootTopics);FConnection := MainForm.ActiveConnection;FRootTopics := FConnection.GetResults(FConnection.SqlProvider.GetSql(qHelpKeyword, [FConnection.EscapeString('CONTENTS')]));treeTopics.RootNodeCount := FRootTopics.RecordCount;end;procedure TfrmSQLhelp.FormClose(Sender: TObject; var Action: TCloseAction);beginAppSettings.WriteInt(asSQLHelpWindowLeft, Left );AppSettings.WriteInt(asSQLHelpWindowTop, Top );AppSettings.WriteIntDpiAware(asSQLHelpWindowWidth, Self, Width);AppSettings.WriteIntDpiAware(asSQLHelpWindowHeight, Self, Height);AppSettings.WriteIntDpiAware(asSQLHelpPnlLeftWidth, Self, pnlLeft.Width);AppSettings.WriteIntDpiAware(asSQLHelpPnlRightTopHeight, Self, memoDescription.Height);Action := caFree;SqlHelpDialog := nil;end;procedure TfrmSQLhelp.treeTopicsFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;Column: TColumnIndex);varResults: TDBQuery;VT: TVirtualStringTree;begin// Topic selectedVT := Sender as TVirtualStringTree;if not Assigned(VT.FocusedNode) thenExit;if VT.HasChildren[VT.FocusedNode] thenExit;FKeyword := VT.Text[VT.FocusedNode, VT.FocusedColumn];lblKeyword.Caption := Copy(FKeyword, 1, 100);MemoDescription.Lines.Clear;MemoExample.Lines.Clear;Caption := DEFAULT_WINDOW_CAPTION;if FKeyword <> '' then tryScreen.Cursor := crHourglass;Results := FConnection.GetResults(FConnection.SqlProvider.GetSql(qHelpKeyword, [FConnection.EscapeString(FKeyword)]));Caption := Caption + ' - ' + FKeyword;MemoDescription.Text := fixNewlines(Results.Col('description', True));MemoExample.Text := fixNewlines(Results.Col('example', True));finallyFreeAndNil(Results);Screen.Cursor := crDefault;end;// Show the user if topic is (not) availableif memoDescription.GetTextLen = 0 thenmemoDescription.Text := _('No help available for this keyword or no keyword was selected.');if memoExample.GetTextLen = 0 thenmemoExample.Text := _('No example available or no keyword was selected.');end;procedure TfrmSQLhelp.treeTopicsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);varResults: PDBQuery;begin// Node gets destroyed - free memory used for bound SQL resultResults := Sender.GetNodeData(Node);if Assigned(Results^) thenResults^.Free;end;procedure TfrmSQLhelp.treeTopicsGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex);begin// Return open or closed book icon for folders, or document icon for topicsif not (Kind in [ikNormal, ikSelected]) thenExit;if Sender.HasChildren[Node] then beginif Sender.Expanded[Node] thenImageIndex := ICONINDEX_CATEGORY_OPENEDelseImageIndex := ICONINDEX_CATEGORY_CLOSED;end elseImageIndex := ICONINDEX_HELPITEM;end;procedure TfrmSQLhelp.treeTopicsGetNodeDataSize(Sender: TBaseVirtualTree;var NodeDataSize: Integer);begin// We bind one TDBQuery to a nodeNodeDataSize := SizeOf(TDBQuery);end;function TfrmSQLhelp.GetHelpResult(Node: PVirtualNode): TDBQuery;varP: PDBQuery;begin// Find right result set for given nodeif treeTopics.GetNodeLevel(Node) = 0 thenResult := FRootTopicselse beginP := treeTopics.GetNodeData(Node.Parent);Result := P^;end;end;procedure TfrmSQLhelp.treeTopicsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);varResults: TDBQuery;begin// Ask result set for node textResults := GetHelpResult(Node);Results.RecNo := Node.Index;CellText := Results.Col('name');end;procedure TfrmSQLhelp.treeTopicsInitChildren(Sender: TBaseVirtualTree; Node: PVirtualNode;var ChildCount: Cardinal);varResults: PDBQuery;VT: TVirtualStringTree;begin// Return number of children for folderVT := Sender as TVirtualStringTree;Results := VT.GetNodeData(Node);Results^ := FConnection.GetResults(FConnection.SqlProvider.GetSql(qHelpKeyword, [FConnection.EscapeString(VT.Text[Node, VT.Header.MainColumn])]));ChildCount := Results.RecordCount;end;procedure TfrmSQLhelp.treeTopicsInitNode(Sender: TBaseVirtualTree; ParentNode,Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);varResults: TDBQuery;ThisFolder, PrevFolder: String;N: PVirtualNode;VT: TVirtualStringTree;RecursionAlarm: Boolean;begin// Display plus button for nodes which are foldersVT := Sender as TVirtualStringTree;Results := GetHelpResult(Node);Results.RecNo := Node.Index;if Results.Col('is_it_category', True) = 'Y' then begin// Some random server versions have duplicated category names in help tables, which would cause// infinite tree recursion, e.g. for "Polygon properties" > "Contents". Do not display these// duplicates as folderRecursionAlarm := False;ThisFolder := Results.Col('name');N := VT.GetPreviousInitialized(Node);while Assigned(N) do beginPrevFolder := VT.Text[N, VT.Header.MainColumn];if VT.HasChildren[N] and ((ThisFolder=PrevFolder) or (ThisFolder='Contents')) then beginRecursionAlarm := True;break;end;N := VT.GetPreviousInitialized(N);end;if not RecursionAlarm thenInclude(InitialStates, ivsHasChildren);end;end;procedure TfrmSQLhelp.ButtonCloseClick(Sender: TObject);beginClose;end;procedure TfrmSQLhelp.FormShow(Sender: TObject);beginTop := AppSettings.ReadInt(asSQLHelpWindowTop);Left := AppSettings.ReadInt(asSQLHelpWindowLeft);Width := AppSettings.ReadIntDpiAware(asSQLHelpWindowWidth, Self);Height := AppSettings.ReadIntDpiAware(asSQLHelpWindowHeight, Self);MakeFullyVisible;pnlLeft.Width := AppSettings.ReadIntDpiAware(asSQLHelpPnlLeftWidth, Self);memoDescription.Height := AppSettings.ReadIntDpiAware(asSQLHelpPnlRightTopHeight, Self);// Apply themed colors in OnShow, not OnCreate, as a check with <> nil returns false otherwiseMainForm.SetupSynEditors(Self);// These SynMemo's don't have any (SQL) highligher, so we have to assign correct colors for basic textmemoDescription.Font.Color := GetThemeColor(clWindowText);MemoExample.Font.Color := GetThemeColor(clWindowText);editFilter.SetFocus;end;procedure TfrmSQLhelp.ButtonOnlinehelpClick(Sender: TObject);begin// Link/redirect to mysql.com for further helpShellExec(APPDOMAIN + 'sqlhelp.php?mysqlversion='+inttostr(FConnection.ServerVersionInt)+'&keyword='+EncodeURLParam(keyword));end;procedure TfrmSQLhelp.memosKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);begin// Esc pressed - close form.// Seems that if we're in a memo, the ButtonClose.Cancel=True doesn't have an effectif Key = VK_ESCAPE thenClose;end;procedure TfrmSQLhelp.SetKeyword(Value: string);varVT: TVirtualStringTree;Node: PVirtualNode;Results: TDBQuery;SearchNoInit: Boolean;begin// Find keyword in treeFKeyword := Value;if FKeyword = '' thenExit;Results := FConnection.GetResults(FConnection.SqlProvider.GetSql(qHelpKeyword, [FConnection.EscapeString(FKeyword)]));while not Results.Eof do beginif Results.Col('is_it_category', true) = 'N' then beginFKeyword := Results.Col('name');break;end;Results.Next;end;FreeAndNil(Results);VT := treeTopics;if (not Assigned(VT.FocusedNode)) // No node selectedor VT.HasChildren[VT.FocusedNode] // Selected node is a folder, not a documentor (VT.Text[VT.FocusedNode, VT.Header.MainColumn] <> FKeyword) // Node is not the right onethen begin// Start searching in initialized nodes, to minimize number of "HELP xyz" queries in certain casesNode := VT.GetFirst;SearchNoInit := False;while Assigned(Node) do beginif (not VT.HasChildren[Node]) and (UpperCase(VT.Text[Node, VT.Header.MainColumn]) = UpperCase(FKeyword)) then beginSelectNode(VT, Node);break;end;if not SearchNoInit then beginNode := VT.GetNextInitialized(Node);if not Assigned(Node) then beginSearchNoInit := True;Node := VT.GetFirst;end;end;if SearchNoInit thenNode := VT.GetNext(Node);end;end;end;procedure TfrmSQLhelp.editFilterChange(Sender: TObject);begintimerSearch.Enabled := False;timerSearch.Enabled := True;editFilter.RightButton.Visible := Trim(editFilter.Text) <> '';end;procedure TfrmSQLhelp.editFilterRightButtonClick(Sender: TObject);begineditFilter.Clear;end;procedure TfrmSQLhelp.DoSearch(Sender: TObject);varNode: PVirtualNode;Search: String;Vis: Boolean;function HasVisibleChildItems(Node: PVirtualNode): Boolean;varN: PVirtualNode;beginN := treeTopics.GetFirstChild(Node);Result := False;while Assigned(N) do beginif treeTopics.HasChildren[N] thenResult := HasVisibleChildItems(N)elseResult := treeTopics.IsVisible[N];if Result thenExit;N := treeTopics.GetNextSibling(N);end;end;begin// Apply filter textScreen.Cursor := crHourglass;treeTopics.BeginUpdate;timerSearch.Enabled := False;Search := Trim(editFilter.Text);if Search = '' then begin// Show all itemsNode := treeTopics.GetFirstInitialized;while Assigned(Node) do begintreeTopics.IsVisible[Node] := True;Node := treeTopics.GetNextInitialized(Node);end;end else begin// Hide non matching child itemsNode := treeTopics.GetFirst;while Assigned(Node) do beginif not treeTopics.HasChildren[Node] thentreeTopics.IsVisible[Node] := Pos(UpperCase(Search), UpperCase(treeTopics.Text[Node, treeTopics.Header.MainColumn])) > 0;Node := treeTopics.GetNext(Node);end;// Hide empty foldersNode := treeTopics.GetFirst;while Assigned(Node) do beginif treeTopics.HasChildren[Node] then beginVis := HasVisibleChildItems(Node);treeTopics.Expanded[Node] := Vis;treeTopics.IsVisible[Node] := Vis;end;Node := treeTopics.GetNext(Node);end;end;treeTopics.EndUpdate;Screen.Cursor := crDefault;end;end.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。