Es increible que con la de gente que ha entrado a ver este post sobre tu pregunta, nadie haya encontrado la razón de tu problema desde que lo planteaste.
Pues resulta que el problema es la composición del escritorio. Yo en el portatil tengo Vista sin la composición de escritorio y transparencia porque usa mucha memoria y el rendimiento es menor. Y en Windows 7 como lo instalé en VirtualBox no se puede habilitar la composición de escritorio ni las transparencias.
La composición de escritorio es lo que permite crear efectos de brillo de las ventanas y las trasparencias. Esto es en Vista y Windows7 si lo tienes con la mejor apariencia. Prueba a cambiar el tema del escritorio a windows clásico o quitar las transparéncias. Seguro que si haces eso no tienes problemas.
Ayer caí en la cuenta que si Chrome se ve transperente o con efecto de brillo por la composición de escritorio ¿que pasará cuando lo meta en el Picture en una aplicación creada con VB6?. Cuando lo incrusto en el Picture se pone negro, como tu decías. Además, no se incrusta en el Picture cuando ya se ha abierto previamente también como tu decías, pero sí la segunda vez. Así que el problema es por tener habilitada la composición de escritorio. Ocurre lo mismo con VB.net.
Por alguna razón que no entiendo, aunque encuentra el Handle no lo incrusta. Así que he recurrido a un código más pesado. He creado un Módulo con el siguiente código:
Código para un Módulo
Option Explicit
'Constantes
'-----------------------------------
Const TH32CS_SNAPHEAPLIST = &H1
Const TH32CS_SNAPPROCESS = &H2
Const TH32CS_SNAPTHREAD = &H4
Const TH32CS_SNAPMODULE = &H8
Const TH32CS_SNAPALL = _
(TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or _
TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)
Const TH32CS_INHERIT = &H80000000
Const MAX_PATH As Integer = 260
Private Declare Function GetPriorityClass Lib "kernel32" _
(ByVal hProcess As Long) As Long
'Estructura para los procesos
'-----------------------------------
Private Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long ' Flags 'Reservado; no usar.
szExeFile As String * MAX_PATH
End Type
'Funciones Api para listar los procesos
'--------------------------------------------------------
Private Declare Function CreateToolhelp32Snapshot Lib _
"kernel32" _
(ByVal lFlags As Long, _
ByVal lProcessID As Long) As Long
Private Declare Function Process32First Lib "kernel32" _
(ByVal hSnapShot As Long, _
uProcess As PROCESSENTRY32) As Long
Private Declare Function _
Process32Next Lib "kernel32" _
(ByVal hSnapShot As Long, _
uProcess As PROCESSENTRY32) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
(ByVal hwnd As Long, _
ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Declare Function IsWindow Lib "user32" _
(ByVal hwnd As Long) As Long
Public Const GW_HWNDNEXT = 2
Public Declare Function GetParent Lib "user32" _
(ByVal hwnd As Long) As Long
Public Declare Function GetWindow Lib "user32" _
(ByVal hwnd As Long, ByVal wCmd As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, ByVal cch As Long) As Long
Public Declare Function GetWindowThreadProcessId Lib "user32" _
(ByVal hwnd As Long, _
lpdwprocessid As Long) As Long
Public Function ProcIDFromWnd(ByVal hwnd As Long) As Long
Dim idProc As Long
GetWindowThreadProcessId hwnd, idProc
ProcIDFromWnd = idProc
End Function
Public Function GetWinHandle(hInstance As Long) As Long
Dim tempHwnd As Long
tempHwnd = FindWindow(vbNullString, vbNullString)
Do Until tempHwnd = 0
If GetParent(tempHwnd) = 0 Then
If hInstance = ProcIDFromWnd(tempHwnd) Then
GetWinHandle = tempHwnd
Exit Do
End If
End If
tempHwnd = GetWindow(tempHwnd, GW_HWNDNEXT)
Loop
End Function
Public Function BuscarHandleChrome() As Long
Dim F As Long, r As Long, x As Long
Dim sWindowText As String * 255 'Variable para introducir el texto de una barra con espacios
Dim sClassName As String * 255
Dim hSnapShot As Long
Dim Name As String * 255
Dim uProcess As PROCESSENTRY32
Dim elemento As ListBox
Dim sTextoBarra As String
Dim sNombreClase As String
Dim shwnd As Long
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0&)
uProcess.dwSize = Len(uProcess)
r = Process32First(hSnapShot, uProcess)
Do While r > 0
r = Process32Next(hSnapShot, uProcess)
shwnd = GetWinHandle(uProcess.th32ProcessID)
x = GetClassName(shwnd, sClassName, 255)
sNombreClase = Left(sClassName, x) '<<----Nombre de Clase
If Trim(sNombreClase) <> "" Then
If IsWindow(shwnd) = 1 Then 'si es una aplicación visible
If IsWindow(shwnd) Then
If sNombreClase = "Chrome_WidgetWin_1" Then BuscarHandleChrome = shwnd
End If
End If
End If
Loop
End Function
Lo que hace es listar las aplicaciones que se están ejecutando y si encuentra una con el nombre de clase "Chrome_WidgetWin_1" entonces introduce el handle en la variable HWNDParent.
Para el Form el siguiente código:
- Añadir un Picture
- Añadir un Botón
- Añadir un control Timer
Option Explicit
'Nombres de clase (ClassName) de Chrome
'Chrome_WidgetWin_1 <---Padre
'Chrome_RenderWidgetHostHWND <---hijo
'//Funciones API para incrustar la aplicación en el picture
Private Declare Function SetParent Lib "user32" _
(ByVal hWndChild As Long, _
ByVal HWNDParent As Long) As Long
Private Declare Function ShowWindow Lib "user32" _
(ByVal hwnd As Long, _
ByVal nCmdShow As Long) As Long
Private Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, _
ByVal hWndInsertAfter As Long, ByVal x As Long, _
ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, _
ByVal wFlags As Long) As Long
'//Ejecuta el programa
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
(ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
'//Función para cerrar la aplicación incrustada
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Const SW_SHOWNORMAL = 1
Const SW_RESTORE = 9
Const SWP_NOZORDER = &H4
Const HWND_TOP = 0
Const WM_SYSCOMMAND = &H112
Const SC_CLOSE = &HF060&
' Función api SetWindowTheme
Private Declare Function SetWindowTheme Lib "UxTheme.dll" ( _
ByVal hwnd As Long, _
ByVal pszSubAppName As Long, _
ByVal pszSubIdList As Long) As Long
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long
'//////////////////////////////////////////////
'//'Variable para el handle padre de Chrome //
'//Debe ser variable pública para que al //
'//cerrar el form únicamente se cierre el //
'//chrome incrustado en el picture y no //
'//otra ventana externa de chrome /////
Dim HWNDParent As Long
'//////////////////////////////////////////////
Dim N&
Private Sub Command1_Click()
If N& = 0 Then ' Si no hay nada dentro del Picture ejecuta el código
'ShellExecute Me.hWnd, "open", "chrome.exe", _
"www.elhacker.net", Environ("programfiles") & "\Google\Chrome\Application\", SW_SHOWNORMAL
Shell Environ("programfiles") & "\Google\Chrome\Application\" & "chrome.exe", vbNormalFocus
Do While HWNDParent = 0
HWNDParent = BuscarHandleChrome
DoEvents
Loop
Do While N& = 0
N& = SetParent(HWNDParent, Picture1.hwnd) 'Meter la apclicación en el picture
DoEvents
Loop
'Refresca Chrome por si no se visualiza correctamente
ShowWindow HWNDParent, SW_RESTORE
'Ajusta la ventana de Chrome al Picture
Call SetWindowPos(HWNDParent, HWND_TOP, 0, 0, _
Picture1.ScaleWidth, _
Picture1.ScaleHeight, _
SWP_NOZORDER)
End If
End Sub
Private Sub Cerrar_Chrome(hwnd As Long)
If HWNDParent <> 0 Then
Call SetParent(HWNDParent, 0) ' Libera el programa
Call SendMessage(HWNDParent, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&) 'Cierra el programa
HWNDParent = 0
End If
End Sub
Private Sub Form_Load()
Picture1.ScaleMode = 3 'pixels <-importante para mover _
y establecer correctamente las dimensiones de la ventana _
de chrome dentro del picture
Timer1.Interval = 1
Timer1.Enabled = True
End Sub
Private Sub Form_Unload(Cancel As Integer)
Call Cerrar_Chrome(HWNDParent) 'Cierra Chrome
End
End Sub
Private Sub Timer1_Timer()
Dim x
x = IsWindow(HWNDParent)
If x = 0 Then
N& = 0
HWNDParent = 0
End If
End Sub
Ahora no falla. El problema que surge ahora es que se ve mal cuando está activada la composición de escritorio. Eso si que ya no tengo ni idea de como arreglarlo.
He probado usando SetWindowTheme para cambiar el estilo de la ventana de Chrome a Windows Clásico. Pero ni por esas, porque aunque sí lo convierte a Windows clásico, continúa estando habilitada la composición de escritorio en la ventana de Chrome. Por eso se ve negro. Creo que la única manera de que se vea bien es utilizando algún código, si existe, que quite la composición del escritorio sólo en la ventana incrustada.
Si te fijas he anulado ShellExecute porque da problemas. Compruebalo tu mismo.
si quieres que abra en un determinada página con shell, basta con añadir la página después de "Chrome.exe" separado por un espacio.
Ejemplo:
Shell Environ("programfiles") & "\Google\Chrome\Application\" & _
"chrome.exe
www.google.co.uk", vbNormalFocus
También:
Shell Environ("programfiles") & "\Google\Chrome\Application\" & _
"chrome.exe " & "
www.google.co.uk", vbNormalFocus
Esta aplicación en principio no sirve para nada, se trata de un ejemplo y luego cada cual lo use, lo arregle, lo modifique y lo mejore como le de la gana si le sirve. A mí me ha servido para viejas apliaciones de 16bits que se me ejecutaban a patanalla completa: cursos de inglés y enciclopedias. Que aunque son viejas apliaciones contienen información muy útil y las sigo usando de vez en cuando. Según lo que sea habrá que cambiar alguna cosa que otra del código. Las correcciones están pensadas para Chrome pero otras aplicaciones no dan los mismos problemas.
Pues así lo dejo para quien le sirva...