[IDE Tool] Help

Everything else that doesn't fall into one of the other PB categories.
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

[IDE Tool] Help

Post by AZJIO »

Help

Download yandex

Opens the help file as an independent window. On the taskbar, the button is not grouped and is separate.
Parameters are passed via command line, so this can be used in any editor (SpiderBasic, AkelPad, Notepad++)

Help.exe WORD [ext=Default [flag=0 [Path Title]]]
Help.exe %WORD (this option will allow you to use the clipboard if the word is from non-Latin letters)
Help.exe %WORD pb
Help.exe %WORD pb flag
Help.exe %WORD pb 0 "C:\Program Files\Purebasic\PureBasic.chm" "HTML Help"

flag [-1, 0, 1, 2]
-1 - selects tab 2 "Search"
0 - selects tab 1 "Index"
1 - debugger only ini and chm help file paths
2 - full debugger, report that windows and window elements are not found
flag + 10 adds search mode

If the parameters "Path" and "Title" are specified, then it does not read the ini file
If only "WORD" is specified, then the Default section will be read in the ini file

For Notepad++ in shortcuts.xml

Code: Select all

<Command name="Help" Ctrl="no" Alt="no" Shift="no" Key="112">&quot;$(NPP_DIRECTORY)\Tools\Help\Help.exe&quot; $(CURRENT_WORD) $(EXT_PART)</Command>
ForHelp.pb

Code: Select all

; Поиск элемента по ID и классу
Procedure enumChildren(hwnd, *ctcl.CtrlClass)
	If hwnd
		GetClassName_(hwnd, @*ctcl\classText, 256)
		If GetDlgCtrlID_(hwnd) = *ctcl\ctrl And *ctcl\classText = *ctcl\class
; 			hWnd_Find = hwnd
			*ctcl\hwnd = hwnd
			ProcedureReturn 0
		EndIf
		ProcedureReturn 1
	EndIf
	ProcedureReturn 0
EndProcedure

Procedure.l isHandle(hwnd.l)
	If Not hwnd
		End
	EndIf
EndProcedure

; Укоротить строку таким способом можно, удлинить нельзя
Procedure TrimQuotes(*a)
	Protected *p.string = @*a
	If Left(*p\s , 1) = Chr(34)
		*p\s = LTrim(*p\s, Chr(34))
	EndIf
	If Right(*p\s , 1) = Chr(34)
		*p\s = RTrim(*p\s, Chr(34))
	EndIf
EndProcedure

; Активировать окно
Procedure SetForegroundWindow(hWnd)
	Protected foregroundThreadID, ourThreadID
	If GetWindowLong_(hWnd, #GWL_STYLE) & #WS_MINIMIZE
		ShowWindow_(hWnd, #SW_MAXIMIZE)
		UpdateWindow_(hWnd)
	EndIf
	foregroundThreadID = GetWindowThreadProcessId_(GetForegroundWindow_(), 0)
	ourThreadID = GetCurrentThreadId_()

	If (foregroundThreadID <> ourThreadID)
		AttachThreadInput_(foregroundThreadID, ourThreadID, #True);
	EndIf

	SetForegroundWindow_(hWnd)

	If (foregroundThreadID <> ourThreadID)
		AttachThreadInput_(foregroundThreadID, ourThreadID, #False)
	EndIf

	InvalidateRect_(hWnd, #Null, #True)
EndProcedure
Help.pb

Code: Select all

EnableExplicit

Global *Lang, UserIntLang

If OpenLibrary(0, "kernel32.dll")
	*Lang = GetFunction(0, "GetUserDefaultUILanguage")
	If *Lang
		UserIntLang = CallFunctionFast(*Lang)
	EndIf
	CloseLibrary(0)
EndIf


Global Dim Lng.s(12)
Lng(1) = "Clipboard?"
Lng(2) = "Failed to get word, use clipboard?"
Lng(3) = "Missing ini file:"
Lng(4) = "Empty path or title in ini file"
Lng(5) = "Section not found"
Lng(6) = "in ini file"
Lng(7) = "Help file (CHM) not found:"
Lng(8) = "Window with title not found:"
Lng(9) = "No highlighted word"
Lng(10) = "No tabs found"
Lng(11) = "Insert field not found"
Lng(12) = "Button not found"

If UserIntLang = 1049
	Lng(1) = "Буфер обмена?"
	Lng(2) = "Не удалось получить слово, использовать буфер обмена?"
	Lng(3) = "Отсутствует ini-файл:"
	Lng(4) = "Пустой путь или заголовок в ini-файле"
	Lng(5) = "Не найдена секция "
	Lng(6) = " в ini-файле"
	Lng(7) = "Не найден файл справки (CHM):"
	Lng(8) = "Не найдено окно с заголовком:"
	Lng(9) = "Нет выделенного слова"
	Lng(10) = "Не найдены вкладки"
	Lng(11) = "Не найдено поле вставки"
	Lng(12) = "Не найдена кнопка"
EndIf


#MinFileSizeCHM = 30
#MinFileSizeINI = 15

Structure CtrlClass
	Control.i
	Class.s
	classText.s
	hwnd.l
EndStructure

XIncludeFile "ForHelp.pb"


Global hWnd_Main, hWnd_Tabs, hWnd_Field, hWnd_Button, hWnd_Search, hWnd_Find
Global ini$, Word$, Ext$, PathCHM$, TitleCHM$
Global CountArg, flgDebug, nArg2
Global k
; Global chmButton
Global ctcl.CtrlClass
ctcl\classText = Space(256)

CountArg = CountProgramParameters()
If CountArg > 0
	Word$ = ProgramParameter(0)
	If CountArg > 1
		Ext$ = ProgramParameter(1)
		If Left(Ext$ , 1) = "."
			Ext$ = LTrim(Ext$, ".")
		EndIf
		If CountArg > 2
			flgDebug = Val(ProgramParameter(2))
			If flgDebug > 8
				flgDebug - 10
				nArg2 = 1
			EndIf
			If flgDebug < -1
				flgDebug = -1
			EndIf
			If flgDebug > 2
				flgDebug = 2
			EndIf
			If CountArg = 5
				PathCHM$ = ProgramParameter(3)
				TitleCHM$ = ProgramParameter(4)
			EndIf
		EndIf
	Else
		Ext$ = "Default"
	EndIf
Else
	If MessageRequester(Lng(1), Lng(2), #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
		Word$ = GetClipboardText()
		Ext$ = "Default"
	Else
		End
	EndIf
EndIf

If CountArg = 5 And flgDebug > 0
	MessageRequester(Str(FileSize(PathCHM$)), PathCHM$ + #CRLF$ + TitleCHM$)
EndIf

; MessageRequester("Сообщение", Ext$ + #CRLF$ +Word$)
If Not (CountArg = 5 And Asc(PathCHM$) And FileSize(PathCHM$) > #MinFileSizeCHM)

	ini$ = GetPathPart(ProgramFilename()) + GetFilePart(ProgramFilename(), #PB_FileSystem_NoExtension) + ".ini"

	If FileSize(ini$) < #MinFileSizeINI
		If flgDebug > 0
			MessageRequester("", Lng(3) + #CRLF$ + ini$)
		EndIf
		End
	EndIf
	If FileSize(ini$) >= #MinFileSizeINI And OpenPreferences(ini$)
		If PreferenceGroup(Ext$)
			; MessageRequester("вошёл в если", "вошёл в если")
			PathCHM$ = ReadPreferenceString("PathCHM", "")
			TrimQuotes(@PathCHM$) ; удаляем кавычки
			If Asc(PathCHM$) And Mid(PathCHM$, 2, 2) <> ":\"
; 				PathCHM$ = GetCurrentDirectory() + PathCHM$
				PathCHM$ = GetPathPart(ProgramFilename()) + PathCHM$
			EndIf
			TitleCHM$ = ReadPreferenceString("TitleCHM", "")
			TrimQuotes(@TitleCHM$) ; удаляем кавычки
; 			If PathCHM$ = "" Or TitleCHM$ = ""
			If Not (Asc(PathCHM$) And Asc(TitleCHM$))
				If flgDebug > 1
					MessageRequester("", Lng(4))
				EndIf
				End
			EndIf
		Else
	; 		Если не создавать секцию Default, то ничего открыто не будет при отсутствии секции по расширению
			If flgDebug > 1
				MessageRequester("", Lng(5) + Chr(34) + Ext$ + Chr(34) + Lng(6))
			EndIf
			End
		EndIf
	Else
	; 	без ini выход, хотя можно сделать ещё 2 параметра чтобы передать заголовок и путь к CHM
		End
	EndIf
EndIf

If FileSize(PathCHM$) < #MinFileSizeCHM
	If flgDebug > 0
		MessageRequester("", Lng(7) + #CRLF$ + PathCHM$)
	EndIf
	End
EndIf
; MessageRequester("Сообщение", PathCHM$ + #CRLF$ +TitleCHM$)

hWnd_Main = FindWindowEx_(0, 0, "HH Parent", TitleCHM$) ; поиск окна
If Not hWnd_Main
	RunProgram(PathCHM$)

	; Вот так мы ищем окно с шагом 100 мсек 30 раз (3 секунды ожидание запуска)
	k = 0
	Repeat
		hWnd_Main = FindWindowEx_(0, 0, "HH Parent", TitleCHM$) ; поиск окна программы
		Delay(100)
		k + 1
		If k > 30
			Break
		EndIf
	Until hWnd_Main
EndIf

If Not hWnd_Main
	If flgDebug > 1
		MessageRequester("", Lng(8) + #CRLF$ + TitleCHM$)
	EndIf
	End
EndIf
SetForegroundWindow(hWnd_Main)

If Not Asc(Word$) ; если нет слова, то и нет смысла искать куда его вставлять, просто разворачиваем справку
	If flgDebug > 1
		MessageRequester("", Lng(9))
	EndIf
	End
EndIf

; Поиск элемента вкладок и активация вкладки
ctcl\Control = 1007
ctcl\Class = "SysTabControl32"
ctcl\hwnd = 0
EnumChildWindows_(hWnd_Main, @enumChildren(), @ctcl) ; hWnd_Main - дескриптор окна, в котором поиск дочерних элементов.
If Not ctcl\hwnd
	If flgDebug > 1
		MessageRequester("", Lng(10))
	EndIf
	End
EndIf
hWnd_Tabs = ctcl\hwnd

; Protected chmButton;, chmField
If flgDebug = -1
	SendMessage_(hWnd_Tabs, #TCM_SETCURFOCUS, 2, 0) ; выбирает вкладку 2 "Поиск"
	; chmButton = 1006
	ctcl\Control = 1001
	ctcl\Class = "Edit"
Else
	SendMessage_(hWnd_Tabs, #TCM_SETCURFOCUS, 1, 0) ; выбирает вкладку 1 "Указатель"
	; chmButton = 3006
	ctcl\Control = 3003
	ctcl\Class = "Edit"
EndIf
ctcl\hwnd = 0


; Поиск элемента поля ввода и ввод текста
k = 0
EnumChildWindows_(hWnd_Main, @enumChildren(), @ctcl)
hWnd_Field = ctcl\hwnd
If hWnd_Field
	SendMessage_(hWnd_Field, #WM_SETTEXT, 0, Word$) ; вставляет текст в поле для поиска
Else
	If flgDebug > 1
		MessageRequester("", Lng(11))
	EndIf
	End
EndIf


; Поиск элемента кнопки и клик по ней
If flgDebug = -1
	ctcl\Control = 1006 ; на вкладке "Поиск"
Else
	ctcl\Control = 3006 ; на вкладке "Указатель"
EndIf
ctcl\Class = "Button"
ctcl\hwnd = 0
EnumChildWindows_(hWnd_Main, @enumChildren(), @ctcl)
hWnd_Button = ctcl\hwnd
If hWnd_Button
	SendMessage_(hWnd_Button, #BM_CLICK, 0, 0) ; эмулирует клик на кнопке
; 		GetClassName_(hWnd_Button, @classText, 256)
; 		MessageRequester("ID " + Str(chmButton), "дескр " + Hex(hWnd_Button) + #CRLF$ + "class " + classText)
Else
	If flgDebug > 1
		MessageRequester("", Lng(12))
	EndIf
	End
EndIf


Delay(150)
keybd_event_(#VK_F6, 0, #KEYEVENTF_EXTENDEDKEY, 0)
Delay(55)
keybd_event_(#VK_F6, 0, #KEYEVENTF_KEYUP | #KEYEVENTF_EXTENDEDKEY, 0)



If nArg2
	Delay(150)
	keybd_event_(#VK_CONTROL, 0, #KEYEVENTF_EXTENDEDKEY, 0)
	Delay(10)
	keybd_event_(#VK_F, 0, #KEYEVENTF_EXTENDEDKEY, 0)
	Delay(55)
	keybd_event_(#VK_F, 0, #KEYEVENTF_KEYUP | #KEYEVENTF_EXTENDEDKEY, 0)
	Delay(10)
	keybd_event_(#VK_CONTROL, 0, #KEYEVENTF_KEYUP | #KEYEVENTF_EXTENDEDKEY, 0)

; 		Здесь нужно проверить что окно Web активно, в фокусе

	; Вот так мы ищем окно с шагом 100 мсек 30 раз (3 секунды ожидание запуска)
	k = 0
	Repeat
		Delay(30)
		hWnd_Search = FindWindowEx_(0, 0, "#32770", 0) ; зависимость от русского текста заголовка
		k + 1
		If k > 20
			Break
		EndIf
	Until hWnd_Search

	If hWnd_Search
		ctcl\Control = 38106 ; поле в диалоге "Найти"
		ctcl\Class = "Edit"
		ctcl\hwnd = 0
		EnumChildWindows_(hWnd_Search, @enumChildren(), @ctcl)
		hWnd_Find = ctcl\hwnd
		If hWnd_Find
			SendMessage_(hWnd_Find, #WM_SETTEXT, 0, Word$) ; вставляет текст в поле для поиска
		Else
			If flgDebug > 1
				End
			EndIf
		EndIf
		PostMessage_(hWnd_Find, #WM_SETFOCUS, 0, 0)
	EndIf
EndIf
Help.ini (UTF-8 + BOM)

Code: Select all

[Default]
PathCHM="..\..\NppHelp.chm"
TitleCHM="Справка Notepad++"

[js]
PathCHM="..\..\Help\JS.chm"
TitleCHM="Справка по JavaScript  (09.09.2019)"
Exact_match=1

[au3]
PathCHM="C:\Program Files\AutoIt3\AutoIt.chm"
TitleCHM="Справка AutoIt"

[pb]
PathCHM="C:\Program Files\Purebasic\PureBasic.chm"
TitleCHM="Справка PureBasic 5.70 (10.02.2019)"
Exact_match=1

[sb]
PathCHM="C:\Program Files\SpiderBasic\SpiderBasic.chm"
TitleCHM="SpiderBasic 2.40 (15.01.2023)"
Exact_match=1

[htm]
PathCHM="..\..\Help\HTML-MERZHEVICH.chm"
TitleCHM="HTML Reference"

[html]
PathCHM="..\..\Help\HTML-MERZHEVICH.chm"
TitleCHM="HTML Reference"

[css]
PathCHM="..\..\Help\CSS-MERZHEVICH.chm"
TitleCHM="CSS Reference"

[wcs]
PathCHM="..\..\updater\helpPECMD.chm"
TitleCHM="PECMD"

[wsc]
PathCHM="..\..\updater\helpPECMD.chm"
TitleCHM="PECMD"
BarryG
Addict
Addict
Posts: 4123
Joined: Thu Apr 18, 2019 8:17 am

Re: [IDE Tool] Help

Post by BarryG »

You don't need a tool to do this. Just put "Win32.hlp" in the "Help" folder and pressing F1 on an API command will open it in that doc. ;)
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

Re: [IDE Tool] Help

Post by AZJIO »

BarryG wrote: Sun Jun 15, 2025 10:10 pm Win32.hlp
This is just a solution for Win32.hlp, but it does not negate the capabilities of the tool. If I use a child window, I cannot open the file in the IDE from the child process. If I use a tool that opens the help file as an independent window, then I can open the sample files from the help file in the IDE.
Post Reply