Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert PR_9884 “Migrate HtmlHelp to CsWin32” and add unit test #10435

Merged
merged 2 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

internal partial class Interop
{
internal static partial class Hhctl
{
public enum HH : uint
{
DISPLAY_TOPIC = 0x00,
HELP_FINDER = 0x00,
DISPLAY_TOC = 0x01,
DISPLAY_INDEX = 0x02,
DISPLAY_SEARCH = 0x03,
SET_WIN_TYPE = 0x04,
GET_WIN_TYPE = 0x05,
GET_WIN_HANDLE = 0x06,
ENUM_INFO_TYPE = 0x07,
SET_INFO_TYPE = 0x08,
SYNC = 0x09,
RESERVED1 = 0x0A,
RESERVED2 = 0x0B,
RESERVED3 = 0x0C,
KEYWORD_LOOKUP = 0x0D,
DISPLAY_TEXT_POPUP = 0x0E,
HELP_CONTEXT = 0x0F,
TP_HELP_CONTEXTMENU = 0x10,
TP_HELP_WM_HELP = 0x11,
CLOSE_ALL = 0x12,
ALINK_LOOKUP = 0x13,
GET_LAST_ERROR = 0x14,
ENUM_CATEGORY = 0x15,
ENUM_CATEGORY_IT = 0x16,
RESET_IT_FILTER = 0x17,
SET_INCLUSIVE_FILTER = 0x18,
SET_EXCLUSIVE_FILTER = 0x19,
INITIALIZE = 0x1C,
UNINITIALIZE = 0x1D,
SAFE_DISPLAY_TOPIC = 0x20,
PRETRANSLATEMESSAGE = 0xFD,
SET_GLOBAL_PROPERTY = 0xFC
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

internal partial class Interop
{
internal static partial class Hhctl
{
public unsafe struct HH_ALINKW
{
public int cbStruct;
public BOOL fReserved;
public char* pszKeywords;
public char* pszUrl;
public char* pszMsgText;
public char* pszMsgTitle;
public char* pszWindow;
public BOOL fIndexOnFail;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

internal partial class Interop
{
internal static partial class Hhctl
{
public unsafe struct HH_FTS_QUERYW
{
public const int DEFAULT_PROXIMITY = -1;

public int cbStruct;
public BOOL fUniCodeStrings;
public char* pszSearchQuery;
public int iProximity;
public BOOL fStemmedSearch;
public BOOL fTitleOnly;
public BOOL fExecute;
public char* pszWindow;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Drawing;

internal partial class Interop
{
internal static partial class Hhctl
{
public unsafe struct HH_POPUPW
{
public int cbStruct;
public IntPtr hinst;
public uint idString;
public char* pszText;
public Point pt;
public COLORREF clrForeground;
public COLORREF clrBackground;
public RECT rcMargins;
public char* pszFont;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;

internal partial class Interop
{
internal static partial class Hhctl
{
[DllImport(Libraries.Hhctrl, CharSet = CharSet.Unicode, ExactSpelling = true)]
public static extern int HtmlHelpW(IntPtr hwndCaller, string? pszFile, HH uCommand, IntPtr dwData);

public static int HtmlHelpW(HandleRef<HWND> hwndCaller, string? pszFile, HH uCommand, IntPtr dwData)
{
int result = HtmlHelpW(hwndCaller.Handle, pszFile, uCommand, dwData);
GC.KeepAlive(hwndCaller.Wrapper);
return result;
}

public static unsafe int HtmlHelpW(HandleRef<HWND> hwndCaller, string? pszFile, HH uCommand, string data)
{
fixed (char* dwData = data)
{
return HtmlHelpW(hwndCaller, pszFile, uCommand, (IntPtr)(void*)dwData);
}
}

public static unsafe int HtmlHelpW<T>(HandleRef<HWND> hwndCaller, string? pszFile, HH uCommand, ref T data) where T : unmanaged
{
fixed (void* dwData = &data)
{
return HtmlHelpW(hwndCaller, pszFile, uCommand, (IntPtr)dwData);
}
}
}
}
5 changes: 0 additions & 5 deletions src/System.Windows.Forms.Primitives/src/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,6 @@ HIGHCONTRASTW
HitTestThemeBackground
HT*
HTREEITEM
HTML_HELP_COMMAND
HtmlHelpW
HH_AKLINK
HH_FTS_QUERY
HH_POPUP
HWND_*
IAccessible
IAutoComplete2
Expand Down

This file was deleted.

71 changes: 34 additions & 37 deletions src/System.Windows.Forms/src/System/Windows/Forms/Help/Help.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

using System.Drawing;
using System.Globalization;
using Windows.Win32.Data.HtmlHelp;
using static Interop.Hhctl;

namespace System.Windows.Forms;

Expand Down Expand Up @@ -95,9 +95,9 @@ public static unsafe void ShowPopup(Control? parent, string caption, Point locat
{
s_windowsFormsHelpTrace.TraceVerbose("Help:: ShowPopup");

HH_POPUP pop = new()
HH_POPUPW pop = new()
{
cbStruct = sizeof(HH_POPUP),
cbStruct = sizeof(HH_POPUPW),
pt = location,
rcMargins = new RECT(-1, -1, -1, -1), // Ignore
clrForeground = new COLORREF(unchecked((uint)-1)), // Ignore
Expand All @@ -109,8 +109,8 @@ public static unsafe void ShowPopup(Control? parent, string caption, Point locat

fixed (char* pszText = caption, pszFont = captionFont)
{
pop.pszText = (sbyte*)pszText;
pop.pszFont = (sbyte*)pszFont;
pop.pszText = pszText;
pop.pszFont = pszFont;
ShowHTML10Help(parent, null, HelpNavigator.Topic, pop);
}
}
Expand Down Expand Up @@ -160,51 +160,48 @@ private static unsafe void ShowHTML10Help(Control? parent, string? url, HelpNavi
object? htmlParam;
if (param is string stringParam)
{
HTML_HELP_COMMAND htmlCommand = MapCommandToHTMLCommand(command, stringParam, out htmlParam);
HH htmlCommand = MapCommandToHTMLCommand(command, stringParam, out htmlParam);
if (htmlParam is string stringHtmlParam)
{
PInvoke.HtmlHelp(handle, pathAndFileName, htmlCommand, stringHtmlParam);
HtmlHelpW(handle, pathAndFileName, htmlCommand, stringHtmlParam);
}
else if (htmlParam is int intParam)
{
PInvoke.HtmlHelp(handle, pathAndFileName, htmlCommand, (nuint)intParam);
HtmlHelpW(handle, pathAndFileName, htmlCommand, intParam);
}
else if (htmlParam is HH_FTS_QUERY query)
else if (htmlParam is HH_FTS_QUERYW query)
{
HH_FTS_QUERY* dwData = &query;
fixed (char* pszSearchQuery = stringParam)
{
query.pszSearchQuery = (sbyte*)pszSearchQuery;
PInvoke.HtmlHelp(handle, pathAndFileName, htmlCommand, (nuint)dwData);
query.pszSearchQuery = pszSearchQuery;
HtmlHelpW(handle, pathAndFileName, htmlCommand, ref query);
}
}
else if (htmlParam is HH_AKLINK aLink)
else if (htmlParam is HH_ALINKW aLink)
{
// According to MSDN documentation, we have to ensure that the help window is up
// before we call ALINK lookup.
PInvoke.HtmlHelp(HWND.Null, pathAndFileName, HTML_HELP_COMMAND.HH_DISPLAY_TOPIC, nuint.Zero);
HtmlHelpW(IntPtr.Zero, pathAndFileName, HH.DISPLAY_TOPIC, IntPtr.Zero);

HH_AKLINK* dwData = &aLink;
fixed (char* pszKeywords = stringParam)
{
aLink.pszKeywords = (sbyte*)pszKeywords;
PInvoke.HtmlHelp(handle, pathAndFileName, htmlCommand, (nuint)dwData);
aLink.pszKeywords = pszKeywords;
HtmlHelpW(handle, pathAndFileName, htmlCommand, ref aLink);
}
}
else
{
Debug.Fail($"Cannot handle HTML parameter of type: {htmlParam!.GetType()}");
PInvoke.HtmlHelp(handle, pathAndFileName, htmlCommand, (string)param);
HtmlHelpW(handle, pathAndFileName, htmlCommand, (string)param);
}
}
else if (param is null)
{
PInvoke.HtmlHelp(handle, pathAndFileName, MapCommandToHTMLCommand(command, null, out htmlParam), nuint.Zero);
HtmlHelpW(handle, pathAndFileName, MapCommandToHTMLCommand(command, null, out htmlParam), IntPtr.Zero);
}
else if (param is HH_POPUP popup)
else if (param is HH_POPUPW popup)
{
HH_POPUP* dwData = &popup;
PInvoke.HtmlHelp(handle, pathAndFileName, HTML_HELP_COMMAND.HH_DISPLAY_TEXT_POPUP, (nuint)dwData);
HtmlHelpW(handle, pathAndFileName, HH.DISPLAY_TEXT_POPUP, ref popup);
}
else if (param.GetType() == typeof(int))
{
Expand Down Expand Up @@ -353,66 +350,66 @@ private static int GetHelpFileType(string? url)
/// <summary>
/// Maps one of the COMMAND_* constants to the HTML 1.0 Help equivalent.
/// </summary>
private static unsafe HTML_HELP_COMMAND MapCommandToHTMLCommand(HelpNavigator command, string? param, out object? htmlParam)
private static unsafe HH MapCommandToHTMLCommand(HelpNavigator command, string? param, out object? htmlParam)
{
htmlParam = param;

if (string.IsNullOrEmpty(param) && (command == HelpNavigator.AssociateIndex || command == HelpNavigator.KeywordIndex))
{
return HTML_HELP_COMMAND.HH_DISPLAY_INDEX;
return HH.DISPLAY_INDEX;
}

switch (command)
{
case HelpNavigator.Topic:
return HTML_HELP_COMMAND.HH_DISPLAY_TOPIC;
return HH.DISPLAY_TOPIC;

case HelpNavigator.TableOfContents:
return HTML_HELP_COMMAND.HH_DISPLAY_TOC;
return HH.DISPLAY_TOC;

case HelpNavigator.Index:
return HTML_HELP_COMMAND.HH_DISPLAY_INDEX;
return HH.DISPLAY_INDEX;

case HelpNavigator.Find:
{
HH_FTS_QUERY ftsQuery = new()
HH_FTS_QUERYW ftsQuery = new()
{
cbStruct = sizeof(HH_FTS_QUERY),
iProximity = (int)HTML_HELP_COMMAND.HH_FTS_DEFAULT_PROXIMITY,
cbStruct = sizeof(HH_FTS_QUERYW),
iProximity = HH_FTS_QUERYW.DEFAULT_PROXIMITY,
fExecute = true,
fUniCodeStrings = true
};
htmlParam = ftsQuery;
return HTML_HELP_COMMAND.HH_DISPLAY_SEARCH;
return HH.DISPLAY_SEARCH;
}

case HelpNavigator.TopicId:
{
if (int.TryParse(param, out int htmlParamAsInt))
{
htmlParam = htmlParamAsInt;
return HTML_HELP_COMMAND.HH_HELP_CONTEXT;
return HH.HELP_CONTEXT;
}

// default to just showing the index
return HTML_HELP_COMMAND.HH_DISPLAY_INDEX;
return HH.DISPLAY_INDEX;
}

case HelpNavigator.KeywordIndex:
case HelpNavigator.AssociateIndex:
{
HH_AKLINK alink = new()
HH_ALINKW alink = new()
{
cbStruct = sizeof(HH_AKLINK),
cbStruct = sizeof(HH_ALINKW),
fIndexOnFail = true,
fReserved = false
};
htmlParam = alink;
return command == HelpNavigator.KeywordIndex ? HTML_HELP_COMMAND.HH_KEYWORD_LOOKUP : HTML_HELP_COMMAND.HH_ALINK_LOOKUP;
return command == HelpNavigator.KeywordIndex ? HH.KEYWORD_LOOKUP : HH.ALINK_LOOKUP;
}

default:
return (HTML_HELP_COMMAND)command;
return (HH)command;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Drawing;

namespace System.Windows.Forms.Tests;

public class HelpTests
{
[Fact]
public void ShowPopupTest()
{
Help.ShowPopup(null, "Popup", Point.Empty);
}
}
Loading