napisał: jalamas postów: 316
umieszczony: 21 listopada 2006 20:19
|
|
Cytat: Na razie pozostaje więc rada jottad-a. Sprawdzać wersję Excela i od niej uzależnić działanie kodu
Artik
Przecież Jottad podał rozwiązanie.Jego, czyli kontrola wersji jest standardem stosowanym w każdej aplikacji
jeśli aplikacja ma pracować w różnych wersjach….
Nie tylko środowiska (Excela), lecz także systemu operacyjnego.
Samo Win API ulega zmianie !!!!!!!!! w zależności od systemu operacyjnego.
Kontrolujemy wersję, w tym na przykład wersję VBA a nawet samego Excela ponieważ już wersja 2000 różni się od 2002 dla niektórych metod i właściwości.
Możemy korzystać z kompilacji warunkowej.
Nie widzę potrzeby uruchamiania fragmentu API dla Userform od 2000 wzwyż
Dlatego też tu na przypadku UserForm ( i nie tylko w Excelu ) dodaję do form swoje własne publiczne Property.
Wykorzystuję fakt, że formę można najpierw w ładować, ustawiać właściwości (zdarzenie Initialize jest wykonywane), a potem "pokazywać"…
Posługuję się swoją funkcją wywołania formularza, a nie np.: UserForm27267.show
I tutaj na przykładzie tego co Jottad napisał:
- formy wywołuję przez nazwę (zamykam zresztą też)
- każda z moich Userform ma kod na przykład takii:
- deklaracje pominęłam… od miejsca….Private mvarMojeModal As Boolean 'local copy
Public Property Let MojeModal(ByVal vData As Boolean)
mvarMojeModal = vData
End Property
Public Property Get MojeModal() As Boolean
MojeModal = mvarMojeModal
End Property
Private Sub UserForm_Activate()
#If VBA6 Then
' nic nie trzeba bo w wywolaniu
#Else
Dim mlHWnd As Long
On Error Resume Next
mlHWnd = FindWindow("XLMAIN", Application.Caption)
If MojeModal Then
EnableWindow mlHWnd, 0
Else
EnableWindow mlHWnd, 1
End If
#End If
End Sub
Private Sub UserForm_Initialize()
Dim hwnd As Long
Dim lngStyle As Long
hwnd = FindWindow(vbNullString, Me.Caption)
lngStyle = GetWindowLong(hwnd, GWL_STYLE)
lngStyle = lngStyle Or WS_MAXIMIZEBOX
lngStyle = lngStyle Or WS_MINIMIZEBOX
SetWindowLong hwnd, GWL_STYLE, lngStyle
DrawMenuBar hwnd
End Sub
Kod modułuSub test()
ShowUserFormModOrLess "frm_moja", False
End Sub
Public Sub ShowUserFormModOrLess(ByVal sFormName As String, _
Optional bModal As Boolean = False)
' jesli potrzebuję a zwykle tak jest wiecej parametrów
' ogólnie dla wszystkich UserForm w swoim projekcie
' mam wzornik UserForm ze zbiorem moich standardowych właściwości
' i jest on w każdej UseForm. Tu przykładowo Property MojeModal
Dim iFrm As Long
With UserForms
'Load
.Add (sFormName)
iFrm = .Count - 1
End With
#If VBA6 Then
With UserForms
With .Item(iFrm)
.MojeModal = bModal
If bModal Then
.Show vbModal
Else
.Show vbModeless
End If
End With
End With
#Else
With UserForms
With .Item(iFrm)
.MojeModal = bModal
.Show
End With
End With
#End If
End Sub Mam nadzieję, ze się nie pomyliłam.... |
|
napisał: r_c postów: 38
umieszczony: 21 listopada 2006 12:47
|
|
ARTIK.
Jeżeli wyrazisz zgodę wyślę TOBIE plik Excela 2003 w pełni niemodalny.
Testując przykład JOTTAD_a zauważyłem pewną dziwną rzecz.
W nowym pliku Excela'2003 umieściłem kody zgodnie ze wskazówkami i po uruchomieniu uzyskałem efekt, który opisujesz. Następnie ustawiłem w okienku Properties > UserForm > ShowModal > False. Zapisałem plik i bezwzględu na ustawienia w Properties ShowModal > False lub True forma jest w 100% niemodalna.?????
Pozdrawiam r_c |
|
napisał: jalamas postów: 316
umieszczony: 20 listopada 2006 23:26
|
|
Zobacz jeszcze na stronie Stephena Bullena:
http://www.oaltd.co.uk/Excel/
FormFun.zip |
|
napisał: jottad postów: 118
umieszczony: 20 listopada 2006 00:08
|
|
Cytat:
Efekt jednak nie jest zadowalający. Owszem, myszką mogę sobie klikać po arkuszu (jest także menu podręczne), jednakże całkowicie straciłem kontrolę nad klawiaturą (żaden z klawiszy nie działa).
Czy coś nie tak zrobiłem, czy to raczej niedoskonałość kodu? ;)
Kod sprawdziłem w Excel 97 i działał prawidłowo! Natomiast w wyższych wersjach Excela, faktycznie występuje problem obsługi klawiatury! Wygląda na to, że jednak kod nalezy nieco zmodyfikować. Jednak w tej chwili trudno jest mi powiedzieć w jaki sposób :(
Muszę poeksperymentować w wolnej chwili.
Prowizorycznym rozwiązaniem moze być użycie Application.Version do sprawdzanie wersji Excela, a następnie uruchamianie kodu UserForm_Activate tylko dla E97. W przypadku pozostałych wersji, można zastosować argument vbModeless przy uruchamianiu formularza.
Pozdrawiam. |
|
napisał: r_c postów: 38
umieszczony: 19 listopada 2006 21:55
|
|
Wyszperane w necie lekko modyfikowane:
Option Explicit
'// Modifications & comments by Ivan F Moala
'// Define the API's for menu's
Private Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long) _
As Long
Private Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) _
As Long
Private Declare Function SetFocus Lib "user32" _
(ByVal hwnd As Long) _
As Long
Private Declare Function DrawMenuBar Lib "user32" _
(ByVal hwnd As Long) _
As Long
Private Declare Function FindWindowA Lib "user32" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) _
As Long
'// Extended Styles
Private Const GWL_EXSTYLE = (-20)
'// Sets a new window style
Private Const GWL_STYLE As Long = (-16)
'// General Windows Styles Bits
'// Sets Min Form to task bar
Private Const WS_EX_APPWINDOW = &H40000
'// WinStyle Sys Menu
Private Const WS_SYSMENU As Long = &H80000
'// WinStyle_MaxButton
Private Const WS_MINIMIZEBOX As Long = &H20000
'// WinStyle_MinButton
Private Const WS_MAXIMIZEBOX As Long = &H10000
Private Const WS_POPUP As Long = &H80000000
Dim lFrmWndHdl As Long
Dim lStyle As Long
Private Sub UserForm_Activate()
lFrmWndHdl = FindWindowA(vbNullString, Me.Caption)
'// The GetWindowLong function retrieves information about the window.
'// The function also retrieves the 32-bit (long) value
'// into the extra window memory of a window.
lStyle = GetWindowLong(lFrmWndHdl, GWL_STYLE)
'// lStyle is the New window style so lets set it up with the following
lStyle = lStyle Or WS_SYSMENU '// SystemMenu
lStyle = lStyle Or WS_MINIMIZEBOX '// With MinimizeBox
lStyle = lStyle Or WS_POPUP ' or WS_MAXIMIZEBOX '// and MaximizeBox
'// Now lets set up our New window the SetWindowLong function changes
'// the attributes of the specified window , given as lFrmWndHdl,
'// GWL_STYLE = New windows style, and our Newly defined style = lStyle
SetWindowLong lFrmWndHdl, GWL_STYLE, (lStyle)
lStyle = GetWindowLong(lFrmWndHdl, GWL_EXSTYLE)
lStyle = lStyle Or WS_EX_APPWINDOW
'// Set the extended window style
SetWindowLong lFrmWndHdl, GWL_EXSTYLE, lStyle
DrawMenuBar lFrmWndHdl
'// Need to set this to make the Form Take
'AppActivate ("Microsoft excel")
SetFocus lFrmWndHdl
End Sub
r_c |
|
napisał: jottad postów: 118
umieszczony: 16 listopada 2006 23:52
|
|
Cytat:
A co z wersją 97? Jak wówczas rozwiązać problem dostępu do arkusza?
Jak wcześniej wspominałem na API to ja się w ogóle nie znam :|
Do poprzednio podanych w moim poscie deklaracji funkcji dodaj:
Private Declare Function EnableWindow Lib "user32" (ByVal hwnd As Long, _
ByVal bEnable As Long) As Long
oraz tak oprogramuj zdarzenie Activate formularza:
Private Sub UserForm_Activate()
Dim mlHWnd As Long
On Error Resume Next
mlHWnd = FindWindow("XLMAIN", Application.Caption)
EnableWindow mlHWnd, 1
End Sub
i będziesz miał niemodalne okno formularza w kazdej wersji Excela ( od 97 oczywiście :) )
Pozdrawiam |
|
napisał: jottad postów: 118
umieszczony: 16 listopada 2006 00:30
|
|
Cytat: He, he. Chciałbyś? co?
W "czystym" VBA - zapomnij.
Ale od czego to forum? Właśnie niedawno natknąłem się na takie rozwiązanie, dość klarownie napisane. Poniżej przepis.
1. Do swojego projektu wstaw moduł klasy i nazwij ten moduł clsMinMaxButton.
Istnieje nieco prostsze rozwiązanie :) Ale, oczywiście też z wykorzystaniem API. Nalezy wkleić na poczatku modułu formularza następujący kod:
Private Declare Function GetWindowLong _
Lib "user32" Alias _
"GetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function FindWindow _
Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function SetWindowLong _
Lib "user32" Alias _
"SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" _
(ByVal hwnd As Long) As Long
Private Const WS_MAXIMIZEBOX As Long = &H10000
Private Const WS_MINIMIZEBOX As Long = &H20000
Private Const GWL_STYLE As Long = (-16)
Private Sub UserForm_Initialize()
Dim hwnd As Long
Dim lngStyle As Long
hwnd = FindWindow(vbNullString, Me.Caption)
lngStyle = GetWindowLong(hwnd, GWL_STYLE)
lngStyle = lngStyle Or WS_MAXIMIZEBOX
lngStyle = lngStyle Or WS_MINIMIZEBOX
SetWindowLong hwnd, GWL_STYLE, lngStyle
DrawMenuBar hwnd
End Sub
Minimalizuje do krawędzi okna aplikacji.
Pozdrawiam |
|
napisał: du_gy postów: 22
umieszczony: 15 listopada 2006 20:55
|
|
czy jest mozliwosc, a jesli tak to jaka dodania do okna UserForm przycisku maksymalizuj i minimalizuj (standartowych przyciskow znajdujacych sie w prawym gornym oknie aplikacji)
tHx |
|
 wstecz 1 dalej  wszystkich stron: 1
|
|