Compare commits

...

19 Commits

Author SHA1 Message Date
emoose
de9f86e878 Form: handle filtering inside RefreshCurrentProfile, handle backspace
Fixes momentary flicker when saving profile, also seemed to help with
the collapsible groups perf issue, so removed the 250ms wait before
applying filter

Updated with NVDRS_APPLICATION_V4 from nvapi r575
2025-07-28 11:04:35 +01:00
emoose
8e0360149c Form: revert DPI change 2025-07-28 10:26:19 +01:00
emoose
bf8aa6c124 Form: remove unused func 2025-07-28 00:37:00 +01:00
emoose
75e729298d Form: add collapsible group headers
Collapsed groups will be saved into HiddenGroups.ini next to NVPI exe

.NET ListView sadly doesn't support collapsing for some reason, but
since it's based on Win32 ListView which does support them, it could
be extended to make use of it

(still had to add extra code to receive the undocumented notify when
user collapses/expands groups though, ugh)

With this the settings refresh is a little slower, added something so
that search filtering only applies 250ms after user finishes typing,
seems to help with that.

(if slower machines have issues with this we can always revert or make
optional)
2025-07-28 00:08:40 +01:00
emoose
5ac60d82ca Form: redirect keypresses from listview to filter textbox 2025-07-27 21:38:55 +01:00
emoose
b2306bb310 Form: update filter textbox font style 2025-07-27 21:09:15 +01:00
emoose
f4e2a2fe69 Form: fix values combobox mispositioning 2025-07-27 20:34:07 +01:00
emoose
ecbc27200a Settings: move smooth motion flip metering to Extra 2025-07-27 19:44:30 +01:00
emoose
06559a5512 Form: add search/filter textbox above setting list, improve high-DPI
frmDrvSettings AutoScaleDimensions changed to improve high DPI displays
2025-07-27 19:40:39 +01:00
emoose
04202e43c7 Reference: re-add pre-526.47 TILEDCACHE 2025-07-27 19:39:02 +01:00
emoose
cde038f53b Settings: correct TILEDCACHE setting ID for later drivers, add TILESIZE and VK settings
Thanks to Guzz on guru3d for pointing them out!
2025-07-26 18:18:30 +01:00
emoose
1980707c13 Settings: move smooth motion debug settings to Extra 2025-07-20 20:58:33 +01:00
emoose
f5e4d76388 Settings: add TILED_CACHE, 3 OpenGL settings, update smooth motion
default

Thanks to @Squall-Leonhart
2025-07-20 20:48:54 +01:00
emoose
89957fcbae Settings: update Smooth Motion settings, add debug settings/flip metering 2025-07-16 23:12:51 +01:00
emoose
0cbafd18a3 CustomSettings: add MinDriver 572.83 to forced DLSS scale 2025-03-20 16:33:34 +00:00
Warkratos
590125369d Update CustomSettingNames.xml
remove the "pre 571 drivers" notice
2025-03-20 16:29:50 +00:00
Warkratos
5a20139f8b Update CustomSettingNames.xml 2025-03-20 16:29:50 +00:00
emoose
a6fde2f6f8 Reference: add names from nvapi/nvcpl
scanner in NVPI didn't pick these up some reason, guess they might be flagged as hidden?
2025-02-23 00:35:53 +00:00
emoose
d5cae1000f Settings: add DLSS-FG flags, RTXHDR bits 2025-02-22 19:28:04 +00:00
10 changed files with 3317 additions and 1070 deletions

View File

@@ -549,7 +549,7 @@ namespace nspector.Common
});
}
private string GetApplicationFingerprint(NVDRS_APPLICATION_V3 application)
private string GetApplicationFingerprint(NVDRS_APPLICATION_V4 application)
{
return $"{application.appName}|{application.fileInFolder}|{application.userFriendlyName}|{application.launcher}";
}

View File

@@ -215,9 +215,9 @@ namespace nspector.Common
protected void AddApplication(IntPtr hSession, IntPtr hProfile, string applicationName)
{
var newApp = new NVDRS_APPLICATION_V3()
var newApp = new NVDRS_APPLICATION_V4()
{
version = nvw.NVDRS_APPLICATION_VER_V3,
version = nvw.NVDRS_APPLICATION_VER_V4,
appName = applicationName,
};
@@ -227,7 +227,7 @@ namespace nspector.Common
}
protected void DeleteApplication(IntPtr hSession, IntPtr hProfile, NVDRS_APPLICATION_V3 application)
protected void DeleteApplication(IntPtr hSession, IntPtr hProfile, NVDRS_APPLICATION_V4 application)
{
var caRes = nvw.DRS_DeleteApplicationEx(hSession, hProfile, ref application);
if (caRes != NvAPI_Status.NVAPI_OK)
@@ -285,16 +285,16 @@ namespace nspector.Common
return settings.ToList();
}
protected List<NVDRS_APPLICATION_V3> GetProfileApplications(IntPtr hSession, IntPtr hProfile)
protected List<NVDRS_APPLICATION_V4> GetProfileApplications(IntPtr hSession, IntPtr hProfile)
{
uint appCount = 512;
var apps = new NVDRS_APPLICATION_V3[512];
apps[0].version = NvapiDrsWrapper.NVDRS_APPLICATION_VER_V3;
var apps = new NVDRS_APPLICATION_V4[512];
apps[0].version = NvapiDrsWrapper.NVDRS_APPLICATION_VER_V4;
var esRes = NvapiDrsWrapper.DRS_EnumApplications(hSession, hProfile, 0, ref appCount, ref apps);
if (esRes == NvAPI_Status.NVAPI_END_ENUMERATION)
return new List<NVDRS_APPLICATION_V3>();
return new List<NVDRS_APPLICATION_V4>();
if (esRes != NvAPI_Status.NVAPI_OK)
throw new NvapiException("DRS_EnumApplications", esRes);

View File

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
@@ -16,6 +17,8 @@ namespace nspector
public event DropFilesNativeHandler OnDropFilesNative;
public event EventHandler<GroupStateChangedEventArgs> GroupStateChanged;
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wPar, IntPtr lPar);
@@ -85,8 +88,14 @@ namespace nspector
if (SubItem >= order.Length)
throw new IndexOutOfRangeException("SubItem "+SubItem+" out of range");
Rectangle lviBounds = Item.GetBounds(ItemBoundsPortion.Entire);
int subItemX = lviBounds.Left;
Rectangle lviBounds;
try
{
lviBounds = Item.GetBounds(ItemBoundsPortion.Entire);
}
catch { return subItemRect; }
int subItemX = lviBounds.Left;
ColumnHeader col;
int i;
@@ -178,6 +187,12 @@ namespace nspector
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_LBUTTONUP)
{
base.DefWndProc(ref m); // Fix for collapsible buttons
return;
}
switch (m.Msg)
{
case WM_PAINT:
@@ -276,6 +291,46 @@ namespace nspector
base.WndProc(ref m);
break;
case WM_NOTIFY:
case WM_REFLECT_NOTIFY:
var nmhdr = (NMHDR)Marshal.PtrToStructure(m.LParam, typeof(NMHDR));
// Check if this is an (undocumented) listview group notification
// https://www.zabkat.com/blog/05Feb12-collapsible-listview.htm
if (nmhdr.code == LVN_GROUPINFO && !_isUpdatingGroups)
{
// Group state has changed - get the group info
var lvGroupInfo = (NMLVGROUP)Marshal.PtrToStructure(m.LParam, typeof(NMLVGROUP));
// Find the corresponding ListViewGroup
ListViewGroup changedGroup = null;
foreach (ListViewGroup group in this.Groups)
{
int? groupId = GetGroupID(group);
if (groupId.HasValue && groupId.Value == lvGroupInfo.iGroupId)
{
changedGroup = group;
break;
}
}
if (changedGroup != null)
{
// Determine if collapsed or expanded based on state
bool isCollapsed = (lvGroupInfo.uNewState & (int)ListViewGroupState.Collapsed) != 0;
// Fire the event
GroupStateChanged?.Invoke(this, new GroupStateChangedEventArgs
{
Group = changedGroup,
IsCollapsed = isCollapsed,
NewState = (ListViewGroupState)lvGroupInfo.uNewState
});
}
}
break;
}
base.WndProc(ref m);
}
@@ -291,5 +346,401 @@ namespace nspector
}
}
}
// Collapsible groups - https://www.codeproject.com/Articles/451742/Extending-Csharp-ListView-with-Collapsible-Groups
private bool _isUpdatingGroups = false;
private const int WM_NOTIFY = 0x004E;
private const int WM_REFLECT_NOTIFY = 0x204E;
private const int LVN_FIRST = -100;
private const int LVN_GROUPINFO = (LVN_FIRST - 88);
private const int LVM_SETGROUPINFO = (LVM_FIRST + 147); // ListView messages Setinfo on Group
private const int WM_LBUTTONUP = 0x0202; // Windows message left button
private delegate void CallBackSetGroupState(ListViewGroup lstvwgrp, ListViewGroupState state);
private delegate void CallbackSetGroupString(ListViewGroup lstvwgrp, string value);
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, LVGROUP lParam);
private static int? GetGroupID(ListViewGroup lstvwgrp)
{
int? rtnval = null;
Type GrpTp = lstvwgrp.GetType();
if (GrpTp != null)
{
PropertyInfo pi = GrpTp.GetProperty("ID", BindingFlags.NonPublic | BindingFlags.Instance);
if (pi != null)
{
object tmprtnval = pi.GetValue(lstvwgrp, null);
if (tmprtnval != null)
{
rtnval = tmprtnval as int?;
}
}
}
return rtnval;
}
private static void setGrpState(ListViewGroup lstvwgrp, ListViewGroupState state)
{
if (Environment.OSVersion.Version.Major < 6) //Only Vista and forward allows collaps of ListViewGroups
return;
if (lstvwgrp == null || lstvwgrp.ListView == null)
return;
if (lstvwgrp.ListView.InvokeRequired)
lstvwgrp.ListView.Invoke(new CallBackSetGroupState(setGrpState), lstvwgrp, state);
else
{
int? GrpId = GetGroupID(lstvwgrp);
int gIndex = lstvwgrp.ListView.Groups.IndexOf(lstvwgrp);
LVGROUP group = new LVGROUP();
group.CbSize = Marshal.SizeOf(group);
group.State = state;
group.Mask = ListViewGroupMask.State;
if (GrpId != null)
{
group.IGroupId = GrpId.Value;
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group);
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group);
}
else
{
group.IGroupId = gIndex;
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group);
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group);
}
lstvwgrp.ListView.Refresh();
}
}
private static void setGrpFooter(ListViewGroup lstvwgrp, string footer)
{
if (Environment.OSVersion.Version.Major < 6) //Only Vista and forward allows footer on ListViewGroups
return;
if (lstvwgrp == null || lstvwgrp.ListView == null)
return;
if (lstvwgrp.ListView.InvokeRequired)
lstvwgrp.ListView.Invoke(new CallbackSetGroupString(setGrpFooter), lstvwgrp, footer);
else
{
int? GrpId = GetGroupID(lstvwgrp);
int gIndex = lstvwgrp.ListView.Groups.IndexOf(lstvwgrp);
LVGROUP group = new LVGROUP();
group.CbSize = Marshal.SizeOf(group);
group.PszFooter = footer;
group.Mask = ListViewGroupMask.Footer;
if (GrpId != null)
{
group.IGroupId = GrpId.Value;
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, GrpId.Value, group);
}
else
{
group.IGroupId = gIndex;
SendMessage(lstvwgrp.ListView.Handle, LVM_SETGROUPINFO, gIndex, group);
}
}
}
public void SetGroupState(ListViewGroupState state)
{
_isUpdatingGroups = true;
foreach (ListViewGroup lvg in this.Groups)
setGrpState(lvg, state);
_isUpdatingGroups = false;
}
public void SetGroupState(ListViewGroup group, ListViewGroupState state)
{
_isUpdatingGroups = true;
setGrpState(group, state);
_isUpdatingGroups = false;
}
public void SetGroupFooter(ListViewGroup lvg, string footerText)
{
setGrpFooter(lvg, footerText);
}
}
/// <summary>
/// LVGROUP StructureUsed to set and retrieve groups.
/// </summary>
/// <example>
/// LVGROUP myLVGROUP = new LVGROUP();
/// myLVGROUP.CbSize // is of managed type uint
/// myLVGROUP.Mask // is of managed type uint
/// myLVGROUP.PszHeader // is of managed type string
/// myLVGROUP.CchHeader // is of managed type int
/// myLVGROUP.PszFooter // is of managed type string
/// myLVGROUP.CchFooter // is of managed type int
/// myLVGROUP.IGroupId // is of managed type int
/// myLVGROUP.StateMask // is of managed type uint
/// myLVGROUP.State // is of managed type uint
/// myLVGROUP.UAlign // is of managed type uint
/// myLVGROUP.PszSubtitle // is of managed type IntPtr
/// myLVGROUP.CchSubtitle // is of managed type uint
/// myLVGROUP.PszTask // is of managed type string
/// myLVGROUP.CchTask // is of managed type uint
/// myLVGROUP.PszDescriptionTop // is of managed type string
/// myLVGROUP.CchDescriptionTop // is of managed type uint
/// myLVGROUP.PszDescriptionBottom // is of managed type string
/// myLVGROUP.CchDescriptionBottom // is of managed type uint
/// myLVGROUP.ITitleImage // is of managed type int
/// myLVGROUP.IExtendedImage // is of managed type int
/// myLVGROUP.IFirstItem // is of managed type int
/// myLVGROUP.CItems // is of managed type IntPtr
/// myLVGROUP.PszSubsetTitle // is of managed type IntPtr
/// myLVGROUP.CchSubsetTitle // is of managed type IntPtr
/// </example>
/// <remarks>
/// The LVGROUP structure was created by Paw Jershauge
/// Created: Jan. 2008.
/// The LVGROUP structure code is based on information from Microsoft's MSDN2 website.
/// The structure is generated via an automated converter and is as is.
/// The structure may or may not hold errors inside the code, so use at own risk.
/// Reference url: http://msdn.microsoft.com/en-us/library/bb774769(VS.85).aspx
/// </remarks>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode), Description("LVGROUP StructureUsed to set and retrieve groups.")]
public struct LVGROUP
{
/// <summary>
/// Size of this structure, in bytes.
/// </summary>
[Description("Size of this structure, in bytes.")]
public int CbSize;
/// <summary>
/// Mask that specifies which members of the structure are valid input. One or more of the following values:LVGF_NONENo other items are valid.
/// </summary>
[Description("Mask that specifies which members of the structure are valid input. One or more of the following values:LVGF_NONE No other items are valid.")]
public ListViewGroupMask Mask;
/// <summary>
/// Pointer to a null-terminated string that contains the header text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the header text.
/// </summary>
[Description("Pointer to a null-terminated string that contains the header text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the header text.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszHeader;
/// <summary>
/// Size in TCHARs of the buffer pointed to by the pszHeader member. If the structure is not receiving information about a group, this member is ignored.
/// </summary>
[Description("Size in TCHARs of the buffer pointed to by the pszHeader member. If the structure is not receiving information about a group, this member is ignored.")]
public int CchHeader;
/// <summary>
/// Pointer to a null-terminated string that contains the footer text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the footer text.
/// </summary>
[Description("Pointer to a null-terminated string that contains the footer text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the footer text.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszFooter;
/// <summary>
/// Size in TCHARs of the buffer pointed to by the pszFooter member. If the structure is not receiving information about a group, this member is ignored.
/// </summary>
[Description("Size in TCHARs of the buffer pointed to by the pszFooter member. If the structure is not receiving information about a group, this member is ignored.")]
public int CchFooter;
/// <summary>
/// ID of the group.
/// </summary>
[Description("ID of the group.")]
public int IGroupId;
/// <summary>
/// Mask used with LVM_GETGROUPINFO (Microsoft Windows XP and Windows Vista) and LVM_SETGROUPINFO (Windows Vista only) to specify which flags in the state value are being retrieved or set.
/// </summary>
[Description("Mask used with LVM_GETGROUPINFO (Microsoft Windows XP and Windows Vista) and LVM_SETGROUPINFO (Windows Vista only) to specify which flags in the state value are being retrieved or set.")]
public int StateMask;
/// <summary>
/// Flag that can have one of the following values:LVGS_NORMALGroups are expanded, the group name is displayed, and all items in the group are displayed.
/// </summary>
[Description("Flag that can have one of the following values:LVGS_NORMAL Groups are expanded, the group name is displayed, and all items in the group are displayed.")]
public ListViewGroupState State;
/// <summary>
/// Indicates the alignment of the header or footer text for the group. It can have one or more of the following values. Use one of the header flags. Footer flags are optional. Windows XP: Footer flags are reserved.LVGA_FOOTER_CENTERReserved.
/// </summary>
[Description("Indicates the alignment of the header or footer text for the group. It can have one or more of the following values. Use one of the header flags. Footer flags are optional. Windows XP: Footer flags are reserved.LVGA_FOOTER_CENTERReserved.")]
public uint UAlign;
/// <summary>
/// Windows Vista. Pointer to a null-terminated string that contains the subtitle text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subtitle text. This element is drawn under the header text.
/// </summary>
[Description("Windows Vista. Pointer to a null-terminated string that contains the subtitle text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subtitle text. This element is drawn under the header text.")]
public IntPtr PszSubtitle;
/// <summary>
/// Windows Vista. Size, in TCHARs, of the buffer pointed to by the pszSubtitle member. If the structure is not receiving information about a group, this member is ignored.
/// </summary>
[Description("Windows Vista. Size, in TCHARs, of the buffer pointed to by the pszSubtitle member. If the structure is not receiving information about a group, this member is ignored.")]
public uint CchSubtitle;
/// <summary>
/// Windows Vista. Pointer to a null-terminated string that contains the text for a task link when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the task text. This item is drawn right-aligned opposite the header text. When clicked by the user, the task link generates an LVN_LINKCLICK notification.
/// </summary>
[Description("Windows Vista. Pointer to a null-terminated string that contains the text for a task link when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the task text. This item is drawn right-aligned opposite the header text. When clicked by the user, the task link generates an LVN_LINKCLICK notification.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszTask;
/// <summary>
/// Windows Vista. Size in TCHARs of the buffer pointed to by the pszTask member. If the structure is not receiving information about a group, this member is ignored.
/// </summary>
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszTask member. If the structure is not receiving information about a group, this member is ignored.")]
public uint CchTask;
/// <summary>
/// Windows Vista. Pointer to a null-terminated string that contains the top description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the top description text. This item is drawn opposite the title image when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.
/// </summary>
[Description("Windows Vista. Pointer to a null-terminated string that contains the top description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the top description text. This item is drawn opposite the title image when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszDescriptionTop;
/// <summary>
/// Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionTop member. If the structure is not receiving information about a group, this member is ignored.
/// </summary>
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionTop member. If the structure is not receiving information about a group, this member is ignored.")]
public uint CchDescriptionTop;
/// <summary>
/// Windows Vista. Pointer to a null-terminated string that contains the bottom description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the bottom description text. This item is drawn under the top description text when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.
/// </summary>
[Description("Windows Vista. Pointer to a null-terminated string that contains the bottom description text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the bottom description text. This item is drawn under the top description text when there is a title image, no extended image, and uAlign==LVGA_HEADER_CENTER.")]
[MarshalAs(UnmanagedType.LPWStr)]
public string PszDescriptionBottom;
/// <summary>
/// Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionBottom member. If the structure is not receiving information about a group, this member is ignored.
/// </summary>
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszDescriptionBottom member. If the structure is not receiving information about a group, this member is ignored.")]
public uint CchDescriptionBottom;
/// <summary>
/// Windows Vista. Index of the title image in the control imagelist.
/// </summary>
[Description("Windows Vista. Index of the title image in the control imagelist.")]
public int ITitleImage;
/// <summary>
/// Windows Vista. Index of the extended image in the control imagelist.
/// </summary>
[Description("Windows Vista. Index of the extended image in the control imagelist.")]
public int IExtendedImage;
/// <summary>
/// Windows Vista. Read-only.
/// </summary>
[Description("Windows Vista. Read-only.")]
public int IFirstItem;
/// <summary>
/// Windows Vista. Read-only in non-owner data mode.
/// </summary>
[Description("Windows Vista. Read-only in non-owner data mode.")]
public IntPtr CItems;
/// <summary>
/// Windows Vista. NULL if group is not a subset. Pointer to a null-terminated string that contains the subset title text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subset title text.
/// </summary>
[Description("Windows Vista. NULL if group is not a subset. Pointer to a null-terminated string that contains the subset title text when item information is being set. If group information is being retrieved, this member specifies the address of the buffer that receives the subset title text.")]
public IntPtr PszSubsetTitle;
/// <summary>
/// Windows Vista. Size in TCHARs of the buffer pointed to by the pszSubsetTitle member. If the structure is not receiving information about a group, this member is ignored.
/// </summary>
[Description("Windows Vista. Size in TCHARs of the buffer pointed to by the pszSubsetTitle member. If the structure is not receiving information about a group, this member is ignored.")]
public IntPtr CchSubsetTitle;
}
public class GroupStateChangedEventArgs : EventArgs
{
public ListViewGroup Group { get; set; }
public bool IsCollapsed { get; set; }
public ListViewGroupState NewState { get; set; }
}
public enum ListViewGroupMask
{
None = 0x00000,
Header = 0x00001,
Footer = 0x00002,
State = 0x00004,
Align = 0x00008,
GroupId = 0x00010,
SubTitle = 0x00100,
Task = 0x00200,
DescriptionTop = 0x00400,
DescriptionBottom = 0x00800,
TitleImage = 0x01000,
ExtendedImage = 0x02000,
Items = 0x04000,
Subset = 0x08000,
SubsetItems = 0x10000
}
public enum ListViewGroupState
{
/// <summary>
/// Groups are expanded, the group name is displayed, and all items in the group are displayed.
/// </summary>
Normal = 0,
/// <summary>
/// The group is collapsed.
/// </summary>
Collapsed = 1,
/// <summary>
/// The group is hidden.
/// </summary>
Hidden = 2,
/// <summary>
/// Version 6.00 and Windows Vista. The group does not display a header.
/// </summary>
NoHeader = 4,
/// <summary>
/// Version 6.00 and Windows Vista. The group can be collapsed.
/// </summary>
Collapsible = 8,
/// <summary>
/// Version 6.00 and Windows Vista. The group has keyboard focus.
/// </summary>
Focused = 16,
/// <summary>
/// Version 6.00 and Windows Vista. The group is selected.
/// </summary>
Selected = 32,
/// <summary>
/// Version 6.00 and Windows Vista. The group displays only a portion of its items.
/// </summary>
SubSeted = 64,
/// <summary>
/// Version 6.00 and Windows Vista. The subset link of the group has keyboard focus.
/// </summary>
SubSetLinkFocused = 128,
}
// Required structures for the notification
[StructLayout(LayoutKind.Sequential)]
public struct NMHDR
{
public IntPtr hwndFrom;
public UIntPtr idFrom;
public int code;
}
[StructLayout(LayoutKind.Sequential)]
public struct NMLVGROUP
{
public NMHDR hdr;
public int iGroupId;
public uint uNewState;
public uint uOldState;
public int state; // Current state
}
}

View File

@@ -344,7 +344,8 @@ namespace nspector.Native.NVAPI2
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)]
internal struct NVDRS_APPLICATION_V3
{
public uint isMetro { get { return ((uint)((bitvector1 & 1))); } set { bitvector1 = ((uint)((value | bitvector1))); } }
public bool isMetro { get { return (bitvector1 & 1) != 0; } set { if (value) bitvector1 |= 1; else bitvector1 &= ~1u; } }
public bool isCommandLine { get { return (bitvector1 & 2) != 0; } set { if (value) bitvector1 |= 2; else bitvector1 &= ~2u; } }
public uint version;
public uint isPredefined;
@@ -359,6 +360,27 @@ namespace nspector.Native.NVAPI2
private uint bitvector1;
}
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)]
internal struct NVDRS_APPLICATION_V4
{
public bool isMetro { get { return (bitvector1 & 1) != 0; } set { if (value) bitvector1 |= 1; else bitvector1 &= ~1u; } }
public bool isCommandLine { get { return (bitvector1 & 2) != 0; } set { if (value) bitvector1 |= 2; else bitvector1 &= ~2u; } }
public uint version;
public uint isPredefined;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]
public string appName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]
public string userFriendlyName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]
public string launcher;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]
public string fileInFolder;
private uint bitvector1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]
public string commandLine;
}
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)]
internal struct NVDRS_PROFILE
{
@@ -388,7 +410,8 @@ namespace nspector.Native.NVAPI2
public static uint NVDRS_APPLICATION_VER_V1 = MAKE_NVAPI_VERSION<NVDRS_APPLICATION_V1>(1);
public static uint NVDRS_APPLICATION_VER_V2 = MAKE_NVAPI_VERSION<NVDRS_APPLICATION_V2>(2);
public static uint NVDRS_APPLICATION_VER_V3 = MAKE_NVAPI_VERSION<NVDRS_APPLICATION_V3>(3);
public static uint NVDRS_APPLICATION_VER = NVDRS_APPLICATION_VER_V3;
public static uint NVDRS_APPLICATION_VER_V4 = MAKE_NVAPI_VERSION<NVDRS_APPLICATION_V4>(4);
public static uint NVDRS_APPLICATION_VER = NVDRS_APPLICATION_VER_V4;
public static uint NVDRS_PROFILE_VER = MAKE_NVAPI_VERSION<NVDRS_PROFILE>(1);
public const uint OGL_IMPLICIT_GPU_AFFINITY_NUM_VALUES = 1;
@@ -549,11 +572,11 @@ namespace nspector.Native.NVAPI2
public static readonly DRS_GetNumProfilesDelegate DRS_GetNumProfiles;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate NvAPI_Status DRS_CreateApplicationDelegate(IntPtr hSession, IntPtr hProfile, ref NVDRS_APPLICATION_V3 pApplication);
public delegate NvAPI_Status DRS_CreateApplicationDelegate(IntPtr hSession, IntPtr hProfile, ref NVDRS_APPLICATION_V4 pApplication);
public static readonly DRS_CreateApplicationDelegate DRS_CreateApplication;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate NvAPI_Status DRS_DeleteApplicationExDelegate(IntPtr hSession, IntPtr hProfile, ref NVDRS_APPLICATION_V3 pApp);
public delegate NvAPI_Status DRS_DeleteApplicationExDelegate(IntPtr hSession, IntPtr hProfile, ref NVDRS_APPLICATION_V4 pApp);
public static readonly DRS_DeleteApplicationExDelegate DRS_DeleteApplicationEx;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@@ -561,7 +584,7 @@ namespace nspector.Native.NVAPI2
public static readonly DRS_DeleteApplicationDelegate DRS_DeleteApplication;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate NvAPI_Status DRS_GetApplicationInfoDelegate(IntPtr hSession, IntPtr hProfile, [MarshalAs(UnmanagedType.LPWStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]StringBuilder appName, ref NVDRS_APPLICATION_V3 pApplication);
public delegate NvAPI_Status DRS_GetApplicationInfoDelegate(IntPtr hSession, IntPtr hProfile, [MarshalAs(UnmanagedType.LPWStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]StringBuilder appName, ref NVDRS_APPLICATION_V4 pApplication);
public static readonly DRS_GetApplicationInfoDelegate DRS_GetApplicationInfo;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@@ -587,7 +610,7 @@ namespace nspector.Native.NVAPI2
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate NvAPI_Status DRS_FindApplicationByNameDelegate(IntPtr hSession, [MarshalAs(UnmanagedType.LPWStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]StringBuilder appName, ref IntPtr phProfile, ref NVDRS_APPLICATION_V3 pApplication);
public delegate NvAPI_Status DRS_FindApplicationByNameDelegate(IntPtr hSession, [MarshalAs(UnmanagedType.LPWStr, SizeConst = (int)NvapiDrsWrapper.NVAPI_UNICODE_STRING_MAX)]StringBuilder appName, ref IntPtr phProfile, ref NVDRS_APPLICATION_V4 pApplication);
public static readonly DRS_FindApplicationByNameDelegate DRS_FindApplicationByName;
public static NvAPI_Status DRS_SetSetting(IntPtr hSession, IntPtr hProfile, ref NVDRS_SETTING pSetting)

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace nspector
{
public class WatermarkTextBox : TextBox
{
private const int WM_PAINT = 0x000F;
private string _watermarkText;
[Category("Appearance")]
public string WatermarkText
{
get => _watermarkText;
set { _watermarkText = value; Invalidate(); }
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT && string.IsNullOrEmpty(this.Text) && !string.IsNullOrEmpty(_watermarkText))
{
using (Graphics g = this.CreateGraphics())
using (Brush brush = new SolidBrush(SystemColors.GrayText))
{
TextFormatFlags flags = TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
TextRenderer.DrawText(g, _watermarkText, this.Font, this.ClientRectangle, SystemColors.GrayText, flags);
}
}
}
}
}

View File

@@ -77,6 +77,7 @@
this.chSettingValueHex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.tbSettingDescription = new System.Windows.Forms.TextBox();
this.pnlListview = new System.Windows.Forms.Panel();
this.txtFilter = new nspector.WatermarkTextBox();
this.tsMain.SuspendLayout();
this.pnlListview.SuspendLayout();
this.SuspendLayout();
@@ -92,7 +93,7 @@
//
// pbMain
//
this.pbMain.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
this.pbMain.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pbMain.Location = new System.Drawing.Point(12, 475);
this.pbMain.Margin = new System.Windows.Forms.Padding(4);
@@ -103,7 +104,7 @@
// tsMain
//
this.tsMain.AllowMerge = false;
this.tsMain.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
this.tsMain.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.tsMain.AutoSize = false;
this.tsMain.BackgroundImage = global::nspector.Properties.Resources.transparent16;
@@ -397,7 +398,7 @@
//
// lblApplications
//
this.lblApplications.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
this.lblApplications.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lblApplications.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(118)))), ((int)(((byte)(185)))), ((int)(((byte)(0)))));
this.lblApplications.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
@@ -549,16 +550,30 @@
//
// pnlListview
//
this.pnlListview.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
this.pnlListview.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.pnlListview.Controls.Add(this.lvSettings);
this.pnlListview.Controls.Add(this.txtFilter);
this.pnlListview.Controls.Add(this.tbSettingDescription);
this.pnlListview.Location = new System.Drawing.Point(12, 52);
this.pnlListview.Name = "pnlListview";
this.pnlListview.Size = new System.Drawing.Size(840, 416);
this.pnlListview.TabIndex = 82;
//
// txtFilter
//
this.txtFilter.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txtFilter.Dock = System.Windows.Forms.DockStyle.Top;
this.txtFilter.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtFilter.Location = new System.Drawing.Point(0, 0);
this.txtFilter.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.txtFilter.Name = "txtFilter";
this.txtFilter.Size = new System.Drawing.Size(2118, 35);
this.txtFilter.TabIndex = 82;
this.txtFilter.WatermarkText = "Search for setting...";
this.txtFilter.TextChanged += new System.EventHandler(this.txtFilter_TextChanged);
//
// frmDrvSettings
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -640,5 +655,6 @@
private System.Windows.Forms.ToolStripMenuItem exportCurrentProfileIncludingPredefinedSettingsToolStripMenuItem;
private System.Windows.Forms.TextBox tbSettingDescription;
private System.Windows.Forms.Panel pnlListview;
private WatermarkTextBox txtFilter;
}
}

View File

@@ -14,6 +14,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static nspector.ListViewEx;
namespace nspector
{
@@ -41,6 +42,8 @@ namespace nspector
private bool isDevMode = false;
private Dictionary<string, bool> _groupCollapsedStates = new();
protected override void WndProc(ref Message m)
{
switch (m.Msg)
@@ -175,9 +178,24 @@ namespace nspector
}
finally
{
lvSettings.EndUpdate();
((ListViewGroupSorter)lvSettings).SortGroups(true);
foreach (ListViewGroup group in lvSettings.Groups)
{
if (_groupCollapsedStates.TryGetValue(group.Header, out bool isCollapsed))
{
lvSettings.SetGroupState(group, isCollapsed ? ListViewGroupState.Collapsed | ListViewGroupState.Collapsible : ListViewGroupState.Normal | ListViewGroupState.Collapsible);
}
else
{
lvSettings.SetGroupState(group, ListViewGroupState.Collapsible);
}
}
ApplySearchFilter();
lvSettings.EndUpdate();
GC.Collect();
for (int i = 0; i < lvSettings.Items.Count; i++)
{
@@ -529,6 +547,67 @@ namespace nspector
tscbShowCustomSettingNamesOnly.Checked = showCsnOnly;
Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
lvSettings.GroupStateChanged += lvSettings_GroupStateChanged;
LoadGroupStates(Path.Combine(AppContext.BaseDirectory, "HiddenGroups.ini"));
}
private void lvSettings_GroupStateChanged(object sender, GroupStateChangedEventArgs e)
{
_groupCollapsedStates[e.Group.Header] = e.IsCollapsed;
SaveGroupStates(Path.Combine(AppContext.BaseDirectory, "HiddenGroups.ini"));
}
private bool SaveGroupStates(string filePath)
{
try
{
using (var writer = new StreamWriter(filePath))
{
foreach (var kvp in _groupCollapsedStates)
{
writer.WriteLine($"{kvp.Key}={kvp.Value}");
}
}
return true;
}
catch
{
return false;
}
}
private bool LoadGroupStates(string filePath)
{
if (!File.Exists(filePath))
return false;
_groupCollapsedStates.Clear();
try
{
foreach (var line in File.ReadAllLines(filePath))
{
int lastEqualIndex = line.LastIndexOf('=');
if (lastEqualIndex != -1)
{
var key = line.Substring(0, lastEqualIndex).Trim();
var valueStr = line.Substring(lastEqualIndex + 1).Trim();
if (bool.TryParse(valueStr, out bool value))
{
_groupCollapsedStates[key] = value;
}
}
}
return true;
}
catch
{
return false;
}
}
public static double ScaleFactor = 1;
@@ -635,6 +714,8 @@ namespace nspector
private void ChangeCurrentProfile(string profileName)
{
txtFilter.Text = "";
if (profileName == GetBaseProfileName() || profileName == _baseProfileName)
{
_CurrentProfile = _baseProfileName;
@@ -1104,6 +1185,8 @@ namespace nspector
private async void RefreshAll()
{
txtFilter.Text = "";
RefreshProfilesCombo();
await ScanProfilesSilentAsync(true, false);
@@ -1293,46 +1376,75 @@ namespace nspector
CopyModifiedSettingsToClipBoard();
}
if (e.Control && e.Alt && e.KeyCode == Keys.D)
else if (e.Control && e.Alt && e.KeyCode == Keys.D)
{
EnableDevmode();
}
if (Debugger.IsAttached && e.Control && e.KeyCode == Keys.T)
else if (Debugger.IsAttached && e.Control && e.KeyCode == Keys.T)
{
TestStoreSettings();
}
if (e.Control && e.KeyCode == Keys.F)
else if (e.Control && e.KeyCode == Keys.F)
{
SearchSetting();
txtFilter.Focus();
}
if (e.KeyCode == Keys.Escape)
else if (e.KeyCode == Keys.Escape)
{
RefreshCurrentProfile();
}
}
private void SearchSetting()
{
string inputString = "";
if (InputBox.Show("Search Setting", "Please enter setting name:", ref inputString, new List<string>(), "", 2048) == System.Windows.Forms.DialogResult.OK)
else if (!e.Control && (e.KeyCode >= Keys.A && e.KeyCode <= Keys.Z ||
e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9 ||
e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9 ||
e.KeyCode == Keys.Space || e.KeyCode == Keys.OemPeriod ||
e.KeyCode == Keys.Back))
{
var lowerInput = inputString.Trim().ToLowerInvariant();
lvSettings.BeginUpdate();
foreach(ListViewItem itm in lvSettings.Items)
txtFilter.Focus();
if (e.KeyCode == Keys.Back)
{
if (!itm.Text.ToLowerInvariant().Contains(lowerInput))
if (txtFilter.Text.Length > 0)
{
itm.Remove();
txtFilter.Text = txtFilter.Text.Substring(0, txtFilter.Text.Length - 1);
}
}
lvSettings.EndUpdate();
else
{
txtFilter.Text += e.Shift ? e.KeyCode.ToString() : e.KeyCode.ToString().ToLower();
}
txtFilter.SelectionStart = txtFilter.Text.Length;
e.SuppressKeyPress = true;
e.Handled = true;
}
}
private void ApplySearchFilter()
{
var lowerInput = txtFilter.Text.Trim().ToLowerInvariant();
if (string.IsNullOrEmpty(lowerInput))
{
return;
}
lvSettings.BeginUpdate();
foreach (ListViewItem itm in lvSettings.Items)
{
if (!itm.Text.ToLowerInvariant().Contains(lowerInput))
{
itm.Remove();
}
}
lvSettings.EndUpdate();
}
private async void txtFilter_TextChanged(object sender, EventArgs e)
{
RefreshCurrentProfile();
txtFilter.Focus(); // Setting listbox sometimes steals focus away
}
private void EnableDevmode()
@@ -1424,7 +1536,6 @@ namespace nspector
}
Clipboard.SetText(sbSettings.ToString());
}
}
}

View File

@@ -204,6 +204,9 @@
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WatermarkTextBox.cs">
<SubType>Component</SubType>
</Compile>
<EmbeddedResource Include="frmBitEditor.resx">
<DependentUpon>frmBitEditor.cs</DependentUpon>
<SubType>Designer</SubType>