Drydo's Blog

Teenager of the Internet

This blog hosted by:
http://blogs.vbcity.com
  Home :: Syndication  :: Login   Community Forums   :: vbCity.com   :: DevCity.NET  

To be quite frank, after 3 months of ASP.NET development, the opportunity to do some down and dirty API programming really appealled to me today. So, the question (as indicated by the title) involved a member wanting to disable the right-click context menu from the Flash ActiveX component when being used in a WinForms application. (See previous blog entries for examples of Flash in VB.NET and communication between the two such as http://blogs.vbcity.com/drydo/archive/2005/10/18/5586.aspx).

The simple answer is to capture the right-click of the Flash Window itself and prevent it from being processed. A little play with Spy++ quickly came up with the answers and the rest was all about good old fashioned subclassing. I must admit it pinched the API declarations from Pinvoke.net and smartened them up a tad and that is pretty much it.

For the record, this is something I've been meaning to do for a while + I can leave work not feeling like some CSS floozy :)

Note: to recreate, create one form, one button and add one Flash Active X control. Copy and Paste as necessary. Tested in VS2005. If you get the dreaded 'Failed to import the ActiveX control' message, check out this workaround

Imports System.Runtime.InteropServices

Public Class Form1

#Region "API Routines"

    <DllImport("User32.dll")> _
   Private Shared Function EnumChildWindows _
       (ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, _
       ByVal lParam As IntPtr) As Boolean
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Private Shared Sub GetClassName(ByVal hWnd As System.IntPtr, _
   ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer)
    End Sub

    <DllImport("user32.dll", CharSet:=CharSet.Auto)> _
    Private Overloads Shared Function SetWindowLong(ByVal hWnd As IntPtr, ByVal
nIndex As Integer, ByVal dwNewLong As Integer) As Integer End Function <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Private Overloads Shared Function SetWindowLong(ByVal hWnd As IntPtr, ByVal
nIndex As Integer, ByVal dwNewLong As FlashCaptureRoutine) As Integer End Function <DllImport("user32.dll", CharSet:=CharSet.Auto)> _ Private Shared Function CallWindowProc(ByVal lpPrevWndFunc As Integer, ByVal
hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer End Function #End Region #Region "Delegates" ' Used for processing Flash Window messages Public Delegate Function FlashCaptureRoutine(ByVal hwnd As Integer, ByVal
Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer ' Used for enumerating child windows Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean #End Region ' Constants Public Const GWL_WNDPROC As Integer = (-4) Public Const WM_ENTERMENULOOP As Integer = &H211 Public Const WM_RBUTTONDOWN As Integer = &H204 Public Const WM_INITMENU = &H116 ' Private vars Private mFlashWindowHandle As IntPtr Private mPreviousHandle As Integer Private isCapturing As Boolean Private Sub Form1_FormClosing(ByVal sender As Object, ByVal
e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing ' Cleanup if appropriate If isCapturing Then CleanupCapture() End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal
e As System.EventArgs) Handles MyBase.Load ' Load the test movie... Me.AxShockwaveFlash1.Movie = "MyTestMovie.swf" Me.AxShockwaveFlash1.Menu = True End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal
e As System.EventArgs) Handles Button1.Click ' Capture / Reset Flash Window Processing as appropriate ' React as approrpiate If isCapturing Then ' Resume CleanupCapture() Else ' Capture events CaptureRightClick() End If ' Switch over the flag isCapturing = Not isCapturing End Sub Private Sub CaptureRightClick() ' Attempt to obtain the Flash Window EnumChildWindows(Me.Handle,
AddressOf EnumWindow, IntPtr.Zero) ' Subclass using new routine storing the old result mPreviousHandle = SetWindowLong(mFlashWindowHandle, GWL_WNDPROC, AddressOf FlashWindowCapture) End Sub Private Sub CleanupCapture() ' Reset back to the original handle... SetWindowLong(mFlashWindowHandle, GWL_WNDPROC, mPreviousHandle) End Sub Private Function FlashWindowCapture(ByVal hwnd As Integer, ByVal Msg As Integer,
ByVal wParam As Integer, ByVal lParam As Integer) As Integer ' Capture the appropriate message and prevent it from being processed Select Case Msg Case WM_RBUTTONDOWN ' Exit Exit Function End Select ' Carry on... Return CallWindowProc(mPreviousHandle, hwnd, Msg, wParam, lParam) End Function Private Function EnumWindow(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean ' Obtain the class name of the child window Dim ClassName As New System.Text.StringBuilder("", 255) GetClassName(Handle, ClassName, ClassName.MaxCapacity) ' Is this the Flash Window? If ClassName.ToString = "MacromediaFlashPlayerActiveX" Then mFlashWindowHandle = Handle End If Return True End Function End Class

posted on Monday, March 03, 2008 4:42 PM

Feedback

No comments posted yet.

Post Feedback

Title:
Name:
Url:
Comments: 
Protected by Clearscreen.SharpHIPEnter the code you see: