News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Contextual help project

Started by mywan, July 18, 2012, 07:31:02 AM

Previous topic - Next topic

jj2007

#15
Thanks, mywan. I attach a new version that hopefully resolves these issues.
The only thing that is bugging me is that it opens as maximised in both FF and MSIE, unless the last FF window closed was not maximised.

I also added a check if the user moved away from the help page, e.g. by clicking on a link; in this case, the old window will not be closed. For example, if the user
- typed string+array in the find box
- presses TAB to move on to the listbox
- presses t to see Tokenisers
- clicks on ltok to see Tokenise lines of text "in place" etc
then a next click on e.g. arr2disk in the listbox does not close the ltok window.
I hope that logic is acceptable :biggrin:

Here is the relevant code (full source attached):

ShowHTML proc uses esi edi   ; show the file in a browser
LOCAL ct, inx
  mov ecx, Matches[4*eax]   ; index passed in eax
  mov inx, ecx      ; there are some API calls that trash ecx
  mov edi, pExeName   ; includes -new-window "file:///x:
  mov eax, Cat$(edi+Replace$(Files$(ecx), "\", "/")+Chr$(34))
  ; CreateProcess:
  Launch eax   ; ignored:, SW_xx   ; Cat$(edi+"file:///"+Replace$(Files$(ecx), "\", "/")+Chr$(34))
  mov edi, hhTitle$(ecx)   ; load window title as identified via title tags
  ; no good: invoke ShellExecute, 0, 0, Files$(ecx), 0, 0, 0
  and ct, 0
  .Repeat
      inc ct
      invoke Sleep, 50
  .Until WinByTitle(edi) || ct>127   ; 50*127=6 seconds
  .if lastWin
   push eax
   .if rv(IsWindow, lastWin)
      .if Instr_(Win$(lastWin), hhTitle$(lastIndex))==1      ; titles must match
         invoke SendMessage, lastWin, WM_CLOSE, 0, 0   ; close previous window
;      .else
;         mov ecx,
Cat$(Win$(lastWin))
;         
deb 1, "You moved on:", $hhTitle$(lastIndex), $ecx
      .endif
   .endif
   pop eax
   and lastWin, 0
  .endif
  .if ct<=127
   mov lastWin, eax   ; valid new window found
   m2m lastIndex, inx   ; remember last Files$() index
   invoke SetForegroundWindow, hMain   ; get dialog to front
   invoke SetFocus, hListbox   ; and enable scrolling through the box
  .else
   MsgBox 0, hhTitle$(inx), "No window found", MB_OK   ; complain
   or lastIndex, -1
  .endif
  ret
ShowHTML endp

mywan

Congrats, you managed to find a chink in my Drawer app. I never give it any thought because all browsers will convert a file path to a file:///url on their own:
C:\Masm32\help\xHelp\masm32\Processor Flags.htm
Or
file:///C:\Masm32\help\xHelp\masm32\Processor%20Flags.htm
To:
file:///C:/Masm32/help/xHelp/masm32/Processor%20Flags.htm
Yet browsers do not understand:
C:/Masm32/help/xHelp/masm32/Processor%20Flags.htm

Now, with your app using 'file:///C:/<etc>' by default, my Drawer app doesn't recognize it as a valid url due to 'file:///' or a valid path due to '/' following the drive assignment. Oversight on my part, but not something I've ever encountered either. At least not as a primary command string rather than as an argument. I need to fix this in my app but I'm not sure why you would bother preprocessing this string when all browsers handle it fine as is.

Also, if I open <file>.htm with your app, then click a new one to open and take more that 5 seconds or so to make a drawer selection then the browser closes and I get an error from the app: MessageBox: No window found, $hhTitle$(inx)  ltok, where ltok is the name of the htm file. Fairly obvious why.

Set back to windows default it works really smoothly on FireFox. On Iron (effectively Chrome) it opens the first selection fine. Then if a second selection is made it opens another tab then closes the browser, leaving no browser open with any help file. If you exit the app it closes the browser also. On IE it merely opens a new window for each selection, leaving as many windows open as selections you made in the app. IE never gets closed except by the user. Perhaps you are expecting a pure 32 bit machine. On windows 7 the invisible windows redirection to 2 separate program files folders, 2 different system folders, etc., is a nightmare. The path you type is not necessarily the path windows uses. When you specified the full path:
"C:\Program Files\Internet Explorer\iexplore.exe"
You explicitly specified a 64 bit option on my machine, which invisibly redirects 'C:\Windows\System32' to 'C:\Windows\SysWOW64'. I'm not sure what MbCopy is? Pure 32 bit apps are fine on my machine and I develop my assembly in pure 32 bit, at least for now.

I really don't think you can solve all these problems the way your going about it. I haven't done any testing myself yet because I had to go under my brothers house to fix an AC problem. Generally I love reading your code. It shows a level of creativity I can only imagine in terms of assembly. I'm working on it though.

jj2007

#17
Quote from: mywan on July 26, 2012, 02:46:45 AMNow, with your app using 'file:///C:/<etc>' by default, my Drawer app doesn't recognize it as a valid url due to 'file:///' or a valid path due to '/' following the drive assignment. Oversight on my part, but not something I've ever encountered either. At least not as a primary command string rather than as an argument. I need to fix this in my app but I'm not sure why you would bother preprocessing this string when all browsers handle it fine as is.

I had problems with MSIE under Windows 7-32, that's why I went for pre-processing. Now I checked under WinXP SP3, and it works indeed with standard backslashes.

What drives me mad is that none of these stupid browsers (I can test only FF and MSIE) implements DDE properly, or has another reasonably simple method to
1. open one window
2. reuse that window if the user wishes to do so

I keep opening new windows or tabs, either maximised at the browser's (not: user's) choice or restored but with changing positions, and as far as DDE and FF are concerned, it's a *very* old bug that was never fixed.

Version D attached, it removes mov byte ptr [esi+Len(esi)], "l" in line 102 which was for testing only.

P.S.: MbCopy is documented here.

dedndave

have you tried using the anchor tag target attribute ?
<a target="_blank|_self|_parent|_top|framename">
Attribute Values
Value      Description
_blank     Opens the linked document in a new window or tab
_self      Opens the linked document in the same frame as it was clicked (this is default)
_parent    Opens the linked document in the parent frame
_top       Opens the linked document in the full body of the window
framename  Opens the linked document in a named frame

jj2007

Dave,

The problem is one step before: The browser receives via ShellExecute, CreateProcess or WWW_OpenURL*) the order to show xx.html; but in all cases, instead of allowing to specify an existing window, the browser opens a new one. Your suggestion is fine but it comes in when the window is already open :(

My first idea was actually a WM_DROPFILES-based server, but FF and MSIE couldn't care less, they just ignore the filenames passed.

*)
https://bugzilla.mozilla.org/show_bug.cgi?id=268840
...
Reproducible: Always
Steps to Reproduce:
Open a bookmark using a third party bookmark manager that uses DDE to
communicate with the browser, e.g. Bookmark Buddy or URL Organizer 2
(urlorg.com/download.shtml).
Actual Results: 
New URL is always opened in accordance with the Tabbed Browsing 'Open links from
other applications in' preference, irrespective of the windowID used, and the
relevant window is not activated.

Expected Results: 
The default behavior for WWW_OpenURL should be as follows:
- a windowID of 0 should open a URL in a new tab
- a windowID of -1 should open a URL in the most recent tab
- a windowID > 0 should open a URL in the corresponding tab*
Whichever window the URL is opened in should be activated.

The 'Open links from other applications' Tabbed Browsing options should be
changed to:
x Use new windows instead of new tabs
x Always open in: [a new tab] OR [a new window] OR [the most recent tab/window]

*This requires WWW_ListWindows to be implemented; see:
https://bugzilla.mozilla.org/show_bug.cgi?id=84363

mywan

ChmWindowD
Under FF, standard windows file association, it appears to work well as you seem to expect.

Under IE, standard windows file association, it still open every click in a new window requiring them all to be manually closed.

Under Iron (Chrome) any spaces in the filename get delimited as separate pages to open in different tabs. Hence "Bare Bones Dialog" attempts to open 3 tabs at "file:///C:/Masm32/help/xHelp/imdialog/Bare", "http://bones/", and "http://dialog.htm/". Using choices with no spaces it opens each each choice properly but in its own tab leaving the previous tab. The entire browser then closes when you exit the app.

Opening with my Drawer app changes none of the behavior above, and can no longer prevent you app from closing my browsers. Except IE which never closes anyway.

I could also test in Opera, Maxthon, and others, but would need to disable some significant modifications to make it meaningful.
____

It's a good idea to think through exactly how you expect it to work. If you are wanting it to work for everybody the way you want it to work for you it is a lost cause. Even if the browsers consistently supported the behavior you apparently seek, a large number of people would install plugins for the explicit purpose of disabling your ability to do that to their browser. Very few users have any interest in a non-tabbed browser, and will be very impatient with any app that tries to demand it. By attempting to demand it your app will consistently close the pages people have open for other reasons. Personally I used a parent container to effectively get tabbed browsing before browsers started supporting it, initially with Maxthon. Even if you got it to work flawlessly in all browsers the way you want very few people would tolerate it.

You basically have two choices. Work from the perspective of a tabbed browser user, and use a plugin to redirect all tabs into a single tab on your own browser. If no FF addon suites you modifying "Close other tabs" to auto close inactive tabs, setting activate new tabs to true, and don't show tabs on last tab to true will get you a tabless FF that operates in a consistent manner with a tabed browser. That addon can also be implemented as a very simple UserJs without the overhead of an addon.

First option (Not ideal):
With the above configuration merely open the help file in a new tab, consistent with the expectations of a tabbed browser. You personal browser will then automatically close the existing tab, or better redirect the existing tab to the new tab location, leaving no tabs for you to deal with. Your app then doesn't need to deal with these issues, the browser does the work for you. Then when exiting your app leave the browser open. It's the ONLY way to be consistent with tabbed and non-tabbed users, and more importantly does not kill everything else a tabbed browser is doing unrelated to your app. Attempting to make my browser operate in a manner consistent with someone else's expectations will never be allowed, no matter how complex a UserJS, sandbox, wrapper, redirect, whatever I have to create to prevent it.

Second option (Best option):
Switch from using <unknown> browser to using hh.exe. This provides consistency across all windows. You can then simply use DDE to redirect the page hh.exe is displaying. Or, not so good, you can simply kill the previous instance of hh.exe you created and open another, just like you are attempting to do with <unknown> browsers. Personally, so long as the app closes anything at all, other than itself, it will never find a use on my machine. Having a config file or command line switches to turn the killing of previous instances or pages on and off is also a viable option.

Questions:
So how do you expect it to actually work for you, and how does that differ from what you are trying to impose on others? Are you mistaken your attempt at getting browsers to cooperate with an attempt to force everybody's browser to be what you want in your browser? A question that needs carefully thought through before any effective GUI development even makes sense. The fact that browser developers woke up to the fact of these inconsistencies in peoples preferences is the source of your present headache. Never force preferences on people, rather do what you need to do to your own browser to consistently get the behavior you want locally. It's not the job of your external app, nor possible, to force your browser preferences on others.

jj2007

Quote from: mywan on July 26, 2012, 01:54:49 PM
ChmWindowD
Under FF, standard windows file association, it appears to work well as you seem to expect.

Under IE, standard windows file association, it still open every click in a new window requiring them all to be manually closed.

Yes, FF works fine but IE refuses to accept Send/PostMessage WM_CLOSE.

QuoteUnder Iron (Chrome) any spaces in the filename get delimited as separate pages to open in different tabs.

Surprising because the proggie hands over a "full path" :(

QuoteIt's a good idea to think through exactly how you expect it to work.
...
First option (Not ideal):
With the above configuration merely open the help file in a new tab, ...

Second option (Best option):
Switch from using <unknown> browser to using hh.exe. This provides consistency... simply use DDE to redirect the page hh.exe is displaying
...
Personally, so long as the app closes anything at all, other than itself, it will never find a use on my machine.

"The app" is a proggie that receives from your favourite editor the info "user has selected string array and pressed F1, so it seems he needs help".

What I expect is to see, after no more than one additional click or keystroke, the screen below. And I expect also that as long as I don't click inside the browser, I can scroll through the list of matches by simply pressing arrow up or arrow down. Sheer luxury, I know ::)

jj2007

What I get instead, if I
- select a much simpler print, then
- guess that it is the \Masm32\help\hlhelp.chm among the ten help files present in that folder,
- open the editor's help menu, where hopefully all ten files are registered
- then click on High Level Macro help,

is the rubbish below. You see the problem?

"The app" uses IE or FF for the exclusive purpose of displaying a user-chosen html page. Unfortunately, there is no easy way to use a WebBrowser control in the same way that you would use a simple RichEdit or "pure" edit control inside your app - that would be the ideal case. Your reflections about user preferences and tabbed browsing etc are valuable, but they apply to a different application: a stand-alone browser. What I need is a control, and I am sure users would look a bit dumb if Notepad suddenly started inserting tabs and playing other gimmick stuff depending on some global preferences set in an unrelated app, say: MS Word...

jj2007

What I also expect from the final version (not the attached one - still not perfect) is that if the user hits F1 and
- there is only one (case-sensitive, full word) match, it will show the html content directly, without any user input;
- if there is no match in the Masm32 chm files for e.g. VirtualAlloc, the app would check if a) Win32.hlp is available and b) the string is long enough to be an API call, and launch it to get immediately this screen (a feature which, by the way, works already fine in RichMasm):

mywan

string_array_xHelp.zip, print_in_HLL.zip, and F1_VirtualAlloc.zip all appear empty to me, no matter which browser I try to download them with.

You can use a COM object in assembly, including the "InternetExplorer.Application" object. Both IE and hh.exe are fully accessible by COM controls, and hh.exe has command line parameters to provide effectively the same function by simple command arguments. The download link under "IE Automation" on this page below provides a working program and source code for IE automation through COM. Play with the included compiled sample program and you'll see exactly what I mean. It's exactly what you need.
http://www.japheth.de/COMnASM.html

That will give you very fine grained control over IE, and works even if the user uninstalled IE.
http://msdn.microsoft.com/en-us/library/aa752084(v=vs.85).aspx

You can also do the same thing with a standard help file, and/or command line parameters to accomplish the same.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms524369(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms670084(v=vs.85).aspx
QuoteIf a window type is not specified, a default window type is used. If the window type or default window type is open, the help topic replaces the current topic in the window.

In your pic above, where you got the page note found. I can't see your source that produced that but it was obviously a syntax problem somewhere. The easiest way to check and see what happened is to right click the error page select properties and check the Address: (URL) that landed you there. The full URL might not be fully visible, but if you select it the rest will scroll into view. I even did a quick and dirty AutoIt script and use my Drawer app to shell your apps command line to it as an argument, then striped the strings I needed from your command string to open the proper .chm file at the proper location. It does in fact work.

jj2007

Quote from: mywan on July 26, 2012, 11:05:14 PM
string_array_xHelp.zip, print_in_HLL.zip, and F1_VirtualAlloc.zip all appear empty to me...
They are png's disguised as zip files. An insider trick to show screenshots - it will work until Hutch stops it one day ;-)

QuoteYou can use a COM object in assembly, including the "InternetExplorer.Application" object. Both IE and hh.exe are fully accessible by COM controls, and hh.exe has command line parameters to provide effectively the same function by simple command arguments. The download link under "IE Automation" on this page below provides a working program and source code for IE automation through COM. Play with the included compiled sample program and you'll see exactly what I mean. It's exactly what you need.
http://www.japheth.de/COMnASM.html
I agree. Unfortunately, while it assembles fine after some mods, I can't get it to link - lots of error messages (and yes I did install the JWasm includes and set the paths etc).

QuoteIn your pic above, where you got the page not found. I can't see your source that produced that but it was obviously a syntax problem somewhere. The easiest way to check and see what happened is to right click the error page select properties and check the Address

I had a bug, it send print%20.html instead of print.htm. Thanks for pointing me to this.

Antariy

Quote from: jj2007 on July 26, 2012, 08:00:46 PM
QuoteUnder Iron (Chrome) any spaces in the filename get delimited as separate pages to open in different tabs.

Surprising because the proggie hands over a "full path" :(

What if replace each space with a "%20" escape code?

mywan

Quote from: Antariy on July 27, 2012, 11:09:04 AM
Quote from: jj2007 on July 26, 2012, 08:00:46 PM
QuoteUnder Iron (Chrome) any spaces in the filename get delimited as separate pages to open in different tabs.

Surprising because the proggie hands over a "full path" :(

What if replace each space with a "%20" escape code?
That may work but I usually just pass quotes as '"strings"'.

jj2007

I tested it with Chrome now and it works just fine: Chrome translates
"C:\...Google\Chrome\Application\chrome.exe" "file:///C:/Masm32/help/xHelp/asmintro/Working With Strings.htm"
into
file:///C:/Masm32/help/xHelp/asmintro/Working%20With%20Strings.htm.
So I wonder what went wrong on your side :(

On a side note: To test this, I had to install Chrome. They trick you into making you believe that you absolutely must use/create a Google account to use Chrome. Well, I have one that I rarely used; when logging in, they tell me about "unusual activity discovered", and that I must absolutely give them my mobile number so that they can send access codes via SMS. Google, go to hell :icon_mrgreen:

Finally I found out that it works fine if you paste a URL. No account needed.

On a programmatical side note:
   Chrome=1
   if Chrome
      invoke ShowWindow, hMain, SW_MINIMIZE
      invoke ShowWindow, hMain, SW_RESTORE
   else
      invoke SetForegroundWindow, hMain   ; get dialog to front
   endif
For some obscure reason that only Google coders will know, SFG for my own window does not work here, in contrast to other FF and MSIE. Again, Google, go to hell :icon_mrgreen:

MichaelW

Well Microsoft, here's another nice mess you've gotten us into.