# Feature Request
In our extension "VR Sketch", the user in VR can edit the m…odel, including opening and closing groups and components. When the user in VR chooses to close a group, we call ``active_model.close_active``. However, when she chooses to open a group, we have no official way to perform the operation in the SketchUp API.
We are currently using a gross and Windows-only hack, using a mixture of approaches, which I paste below in case somebody else is interested.
Maybe a more generally useful solution would be to let ``Sketchup.send_action(id)`` trigger context menu items. The code below is a hack to dig out the id corresponding to the "Edit group" context menu. This id is variable, so we need to emulate the user clicking through the menu until he reaches the right menu command, and read the current id. I guess that the id is variable because the context menu is itself variable, and any number of extensions can add stuff to it. Still, if "edit group" and most of the other standard items had a fixed and public id, it would solve the problem.
```#! ruby
require 'fiddle'
require 'fiddle/types'
require 'fiddle/import'
#...
module Kernel32
extend Fiddle::Importer
dlload 'kernel32.dll'
include Fiddle::Win32Types
extern 'DWORD GetCurrentThreadId()'
end
module User32
extend Fiddle::Importer
dlload 'user32.dll'
include Fiddle::Win32Types
extern 'HWND GetAncestor(HWND, UINT)'
#extern 'BOOL EnumThreadWindows(DWORD, WNDENUMPROC, LPARAM)'
extern 'BOOL EnumThreadWindows(DWORD, PVOID, PVOID)'
end
def hack_prepare_open_group()
# call this once, e.g. when your extension loads
require 'Win32API'
@hack_GetMenu = Win32API.new("user32.dll", "GetMenu", ['L'], 'L')
@hack_GetMenuItemCount = Win32API.new("user32.dll", "GetMenuItemCount", ['L'], 'I')
@hack_GetMenuItemID = Win32API.new("user32.dll", "GetMenuItemID", ['L', 'I'], 'I')
@hack_GetSubMenu = Win32API.new("user32.dll", "GetSubMenu", ['L', 'I'], 'L')
@hack_SendMessage = Win32API.new("user32.dll", "SendMessage", ['L', 'I', 'L', 'L'], 'L')
# the fiddle parts are based on https://github.com/SketchUp/testup-2/blob/master/src/testup/win32.rb
thread_id = Kernel32.GetCurrentThreadId()
main_hwnd = 0
enumWindowsProc = Fiddle::Closure::BlockCaller.new(Fiddle::TYPE_INT,
[Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP]) { |hwnd, lparam|
hwnd = User32.GetAncestor(hwnd, 3) # GA_ROOTOWNER
hmenu = @hack_GetMenu.call(hwnd)
next 1 if hmenu == 0
heditmenu = @hack_GetSubMenu.call(hmenu, 1)
next 1 if heditmenu == 0
menulength = @hack_GetMenuItemCount.call(heditmenu)
contextmenu = @hack_GetSubMenu.call(heditmenu, menulength - 1)
next 1 if contextmenu == 0
main_hwnd = hwnd
next 0
}
User32.EnumThreadWindows(thread_id, enumWindowsProc, 0)
UI.messagebox("Cannot get the top-level SketchUp window's Edit menu. Opening groups in VR will not work") if main_hwnd == 0
@hack_hwnd = main_hwnd
end
def hack_open_group(model, grp)
if (grp.is_a? Sketchup::Group) || (grp.is_a? Sketchup::ComponentInstance)
found = 0
model.active_entities.each { |ent|
if ent == grp
found += 1
end
}
if found > 0
Sketchup.active_model.selection.clear
Sketchup.active_model.selection.add(grp)
hwnd = @hack_hwnd
hmenu = @hack_GetMenu.call(hwnd)
@hack_SendMessage.call(hwnd, 0x0116, hmenu, 0)
heditmenu = @hack_GetSubMenu.call(hmenu, 1)
@hack_SendMessage.call(hwnd, 0x0117, heditmenu, 1)
menulength = @hack_GetMenuItemCount.call(heditmenu)
contextmenu = @hack_GetSubMenu.call(heditmenu, menulength - 1)
id = @hack_GetMenuItemID.call(contextmenu, 0)
Sketchup.send_action(id)
else
puts("open_close_group: group not in active_entities")
end
else
puts("open_close_group: not a group id")
end
end
```