ramses
asked on
Usercontrol Question + (continued)
Is there a bulletproof way to prevent resizing of a Usercontrol in VB5CCE?
(this question is started at 10 points, but I'll increase as soon as I have more points)
This question is started in
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20175004
Please read that thread before adding comments here
Ramses
(this question is started at 10 points, but I'll increase as soon as I have more points)
This question is started in
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20175004
Please read that thread before adding comments here
Ramses
That means that you removed or altered the code concerning the static variable. Can you post the current callback-procedure? We'll do something about it.
Have you read my last comment completely? Have you added the WM_MOVE?
rspahitz: you're right for "main" windows in windows 98+ and windows NT4+. But when you drag a control's handles on a form in visual basic, these rules do not apply. Visual basic only draws the content once the handles are released. To do so, VB doesn't sent any message (not even a HITTEST) to the control while you drag the handles. Once the handles are released though, the appropriate messages (WM_MOVE, WM_SIZE et al.) are sent.
Abel
Have you read my last comment completely? Have you added the WM_MOVE?
rspahitz: you're right for "main" windows in windows 98+ and windows NT4+. But when you drag a control's handles on a form in visual basic, these rules do not apply. Visual basic only draws the content once the handles are released. To do so, VB doesn't sent any message (not even a HITTEST) to the control while you drag the handles. Once the handles are released though, the appropriate messages (WM_MOVE, WM_SIZE et al.) are sent.
Abel
ASKER
Abel, I have read your comment. Hold on, I'll get the code
ASKER
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Static RecursiveMsg As Boolean
'Static OldMsg As Long
'Dim xctl As UserControl1
Select Case uMsg
Case WM_WINDOWPOSCHANGED, WM_SIZE
If Not RecursiveMsg Then
RecursiveMsg = True
'Debug.Print "Yep, min/max"
gUserCtl.Height = 200
gUserCtl.Width = 200
RecursiveMsg = False
End If
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Case Else
'If uMsg <> OldMsg Then
'Debug.Print "Message called: " + Trim(Str(uMsg))
'OldMsg = uMsg
'End If
WindowProc = CallWindowProc(lpPrevWndPr oc, hw, uMsg, wParam, lParam)
End Select
End Function
note the comments (')
these constants are declared at module level:
Private Const WM_WINDOWPOSCHANGED = &H47
Private Const GWL_WNDPROC = -4
Private Const WM_GETMINMAXINFO = &H24
Private Const WM_MOVE = &H3
Private Const WM_SIZE = &H5
Private Const WM_PAINT = &HF
Private Const WM_ERASEBKGND = &H14
Private Const WM_SETCURSOR = &H20
Private Const WM_MOUSEACTIVATE = &H21
Private Const WM_WINDOWPOSCHANGING = &H46
Private Const WM_NCCALCSIZE = &H83
Private Const WM_NCHITTEST = &H84
Private Const WM_NCPAINT = &H85
Static RecursiveMsg As Boolean
'Static OldMsg As Long
'Dim xctl As UserControl1
Select Case uMsg
Case WM_WINDOWPOSCHANGED, WM_SIZE
If Not RecursiveMsg Then
RecursiveMsg = True
'Debug.Print "Yep, min/max"
gUserCtl.Height = 200
gUserCtl.Width = 200
RecursiveMsg = False
End If
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Case Else
'If uMsg <> OldMsg Then
'Debug.Print "Message called: " + Trim(Str(uMsg))
'OldMsg = uMsg
'End If
WindowProc = CallWindowProc(lpPrevWndPr
End Select
End Function
note the comments (')
these constants are declared at module level:
Private Const WM_WINDOWPOSCHANGED = &H47
Private Const GWL_WNDPROC = -4
Private Const WM_GETMINMAXINFO = &H24
Private Const WM_MOVE = &H3
Private Const WM_SIZE = &H5
Private Const WM_PAINT = &HF
Private Const WM_ERASEBKGND = &H14
Private Const WM_SETCURSOR = &H20
Private Const WM_MOUSEACTIVATE = &H21
Private Const WM_WINDOWPOSCHANGING = &H46
Private Const WM_NCCALCSIZE = &H83
Private Const WM_NCHITTEST = &H84
Private Const WM_NCPAINT = &H85
Maybe this helps: make a seperate case for WM_SIZE and copy and paste the code. Make a new static variable for it. It's not so neat, but it'll show where the problem is. We'll beautify it later on.
I'm going to an appointment, I hope to be back in an hour or four to help you further.
Abel
I'm going to an appointment, I hope to be back in an hour or four to help you further.
Abel
ASKER
OK
Just scream when you're back
Ramses
Just scream when you're back
Ramses
declare a Static boolean variable in your resize event something like this:
Private Sub UserControl_Resize()
Static sblnResize As Boolean
If sblnResize Then Exit Sub
sblnResize = True
'resize code here
sblnResize = False
End Sub
Private Sub UserControl_Resize()
Static sblnResize As Boolean
If sblnResize Then Exit Sub
sblnResize = True
'resize code here
sblnResize = False
End Sub
ASKER
No go Abel,
even with the 2nd case statement and static var, still Error 28 a few 1000 times after each other...
emouro, I'll try right away, hold on...
RAmses
even with the 2nd case statement and static var, still Error 28 a few 1000 times after each other...
emouro, I'll try right away, hold on...
RAmses
ASKER
No Emouro, doesn't work... sorry
Abel,
I've also tried adding error handling like this:
Function WindowProc...
...
ON ERROR RESUME NEXT
If err.number=28 then
Unhook
Msgbox "Stack Overflow Error, Hook disabled"
Exit Function
else
Err.Clear
End if
...
Suprizingly, I never get the Msgbox with Stack Overflow error...
But I see that, when adding the usercontrol to the form, the windowproc keeps getting called over and over again, until I close the form. Then I reopen the form and find that the hook is somewhat working correctly, except for the fact that, when dragging some handles, the size is still not limited, but set to what the user has dragged.
Ramses
Abel,
I've also tried adding error handling like this:
Function WindowProc...
...
ON ERROR RESUME NEXT
If err.number=28 then
Unhook
Msgbox "Stack Overflow Error, Hook disabled"
Exit Function
else
Err.Clear
End if
...
Suprizingly, I never get the Msgbox with Stack Overflow error...
But I see that, when adding the usercontrol to the form, the windowproc keeps getting called over and over again, until I close the form. Then I reopen the form and find that the hook is somewhat working correctly, except for the fact that, when dragging some handles, the size is still not limited, but set to what the user has dragged.
Ramses
If you want a fixed size, do this:
Private Sub UserControl_Resize()
UserControl.Height = 2000
UserControl.Width = 3000
End Sub
Private Sub UserControl_Resize()
UserControl.Height = 2000
UserControl.Width = 3000
End Sub
ASKER
I know vb fires a resize event when creating an object (even when it's a screensaver) but what causes this eternal loop when creating a usercontrol?
ASKER
emoureau, please read the history of this question before commenting here
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20175004
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20175004
You didn't have this eternal loop in the previous version of your code, did you? I mean, without the WM_SIZE in it. I wonder what went wrong. Can you go back to that code and get it to work again?
Also, very important here: after you alter the window procedure, make sure that you recreate the control: delete the control on the form and create a new one.
Also, very important here: after you alter the window procedure, make sure that you recreate the control: delete the control on the form and create a new one.
You know, I hate to suggest this, but the more I read the more I realize that when you're working with a flawed component which already has a fix, it's rarely worthwhile to try to find a workaround for the bug. the amount of time you waste with this is usually ofset by the cost of buying the upgraded tool.
Therefore, my suggestion is to abandon the flawed tool and upgrade to VB 6.0 Professional (at about $600 or less.) Let's see...at a low $20 per hour you break even after 30 hours of time wasted...and you get the benefit of other new and improved tools.
Therefore, my suggestion is to abandon the flawed tool and upgrade to VB 6.0 Professional (at about $600 or less.) Let's see...at a low $20 per hour you break even after 30 hours of time wasted...and you get the benefit of other new and improved tools.
Eureka! Maybe this is it! Don't know if it will solve your problem, but maybe at least the stack-overflow. Remove the DefWindowProc line. You don't need it and it can cause this behaviour.
> Suprizingly, I never get the Msgbox with Stack Overflow error...
That is correct, VB doesn't allow you to do anything about it. It's a more severe error than can be handled by VB, and definitely not by Err.Clear.
> the windowproc keeps getting called over and over again
with the same event? If this still is the case after you remove the DefWindowProc line, please print the event and see if it's the same all the time.
> the size is still not limited, but set to what the user has dragged.
In what events of the UserControl do you call the hook function?
> Suprizingly, I never get the Msgbox with Stack Overflow error...
That is correct, VB doesn't allow you to do anything about it. It's a more severe error than can be handled by VB, and definitely not by Err.Clear.
> the windowproc keeps getting called over and over again
with the same event? If this still is the case after you remove the DefWindowProc line, please print the event and see if it's the same all the time.
> the size is still not limited, but set to what the user has dragged.
In what events of the UserControl do you call the hook function?
ASKER
AbeL
It doesn't. I have removed the DefWindowproc, but the eternal calling still happens. Furthermore, the hook is set in both the InitProperties and Show eventprocedure of the Usercontrol. I'll look right away what message is getting called.
rspahitZ
IF I was a programming and actually getting payed for it, I might be able to purchase VB 6.0 Professional. In fact, I would buy it, as well as a higher programming language 4 windows, like C++ or delphi. Since many things I want to program, I cannot do with my CCE edition. Unfortunally I cannot pay $ 1.000 for VB6 pro, so I have to do with what I have.
I do have managed to "steal" some controls from the Service Packs and licenses from VB4 so I have almost all the controls available. For now, I'm stuck with what I can get my hands on for a low price. Before, I could get hands on Crazy Bytes Cd's, stuffed with all kinds of things, including VB PRO's, but lately, I cannot find them anymore. So if anyone from belgium's around here who knows where to get the CB's, please let me know. (text repeated in Dutch below)
Belgen, als je weet waar ik aan de Crazy-Bytes CD's met VB6 pro en/of MSVC kan geraken, laat aub iets weten
Maybe, someone can send me a copied cd of their version of MSVB6PRO? Until then, I'm stuck with CCE and I do believe there must be a bullet-proof way to limit a usercontrols size.
It doesn't. I have removed the DefWindowproc, but the eternal calling still happens. Furthermore, the hook is set in both the InitProperties and Show eventprocedure of the Usercontrol. I'll look right away what message is getting called.
rspahitZ
IF I was a programming and actually getting payed for it, I might be able to purchase VB 6.0 Professional. In fact, I would buy it, as well as a higher programming language 4 windows, like C++ or delphi. Since many things I want to program, I cannot do with my CCE edition. Unfortunally I cannot pay $ 1.000 for VB6 pro, so I have to do with what I have.
I do have managed to "steal" some controls from the Service Packs and licenses from VB4 so I have almost all the controls available. For now, I'm stuck with what I can get my hands on for a low price. Before, I could get hands on Crazy Bytes Cd's, stuffed with all kinds of things, including VB PRO's, but lately, I cannot find them anymore. So if anyone from belgium's around here who knows where to get the CB's, please let me know. (text repeated in Dutch below)
Belgen, als je weet waar ik aan de Crazy-Bytes CD's met VB6 pro en/of MSVC kan geraken, laat aub iets weten
Maybe, someone can send me a copied cd of their version of MSVB6PRO? Until then, I'm stuck with CCE and I do believe there must be a bullet-proof way to limit a usercontrols size.
Or how about, since it sounds like it's not proprietary code, that you make the code available to a trusted soul here to compile it for you?!
ASKER
The message being called over and over again IS...
trtrtrtrtrtrtrtrtrtrtrtr
15
WM_PAINT
pretty strange for an empty usercontrol huh?
Ramses
trtrtrtrtrtrtrtrtrtrtrtr
15
WM_PAINT
pretty strange for an empty usercontrol huh?
Ramses
ASKER
Yes rspahitz that IS a possibility, but most controls I make are controls that are:
- invisable at runtime
- have no interface on the usercontrol
- have a picture on it to show what the control's about
(like the CommonDialog Control)
It would be somehow stupide to ask someone to compile my ocx's each time while I can compile them myself. Think man, THINK of a bullet-proof way to limit a usercontrol's size! It MUST be possible.
Everyone
Are callbacks for the WindowMessages the only things that get fired upon resizing a control?
WAIT a minute!
WOuldn't it be possible to make a ocx or some other plug-in object that I can use in my ocx's, in C++ that checks the size of it's parent and prevents resizing?
Ramses
- invisable at runtime
- have no interface on the usercontrol
- have a picture on it to show what the control's about
(like the CommonDialog Control)
It would be somehow stupide to ask someone to compile my ocx's each time while I can compile them myself. Think man, THINK of a bullet-proof way to limit a usercontrol's size! It MUST be possible.
Everyone
Are callbacks for the WindowMessages the only things that get fired upon resizing a control?
WAIT a minute!
WOuldn't it be possible to make a ocx or some other plug-in object that I can use in my ocx's, in C++ that checks the size of it's parent and prevents resizing?
Ramses
> Wouldn't it be possible to make a ocx or some other plug-in object that I
> can use in my ocx's, in C++ that checks the size of it's parent and prevents resizing?
I can do that in a breeze, but I'm afraid I'd have to charge you for that.
I have to go (again). I'll look through your comments later this evening. One thought though: is VB5CCE still downloadable? I can download it to try to mimick your situation.
Abel
> can use in my ocx's, in C++ that checks the size of it's parent and prevents resizing?
I can do that in a breeze, but I'm afraid I'd have to charge you for that.
I have to go (again). I'll look through your comments later this evening. One thought though: is VB5CCE still downloadable? I can download it to try to mimick your situation.
Abel
ASKER
Yes it is! Hold on, I'll look it up. Once sec...
ASKER
http://msdn.microsoft.com/downloads/default.asp?URL=/code/sample.asp?url=/msdn-files/027/000/133/msdncompositedoc.xml
That's where you can download VB5CCE Final 4 Free
That's where you can download VB5CCE Final 4 Free
Ok, I've read the comments so far that I didn't read yet. Here are some answers to open questions in this thread.
abel > Can you go back to that code and get it to work again?
Have you done this already? You didn't mention it anymore
ramses > but the eternal calling still happens.
Can you remove the commented code and post a cleansed copy here? Test it again after you have cleansed it and then post it, please. Make that a copy of *all* your code (like my original code-posting).
ramses > I could get hands on Crazy Bytes Cd's
Be careful with statements like that on EE. In europe, there's a manhunt going on after people selling CB cd's and the like and they succeed more often lately. Also, it is illegal to trade on EE, read the guidelines.
ramses > pretty strange for an empty usercontrol huh?
No, a WM_PAINT is *always* sent. But what I don't get is why that is causing a recursive loop. You don't handle the WM_PAINT, do you?
ramses > Are callbacks for the WindowMessages the only things that get fired upon resizing a control?
You might want to read something about windows, messages and callbacks. An unmissable book on the shelf when you work with these and VB is "Visual Basic Programming Guide To The Win32 API" by the famous Dan Appleman. You might be able to get an old copy of the book for little money. The first edition was written for VB4 but that shouldn't really be a matter.
But you want an answer, I guess, not some moralistic propaganda. The answer is "yes and no". Callbacks are not fired and you can put as many of them in a line as you like (but this is very dangerous). At this moment we are subclassing the control, but we could also hook it. But that would only complicate the matter and wouldn't give us any more possibilities. "Firing" is a VB-thing and something that large companies do. Windows "sends" messages to get things done, like WM_CREATE to create a window, WM_DESTROY to destroy a window or WM_MOVE to move a window. Try it out with SendMessage, you'll be surprised of the many posibilities.
In short: callbacks don't get fired, in VB-terms, messages get fired, in fact, an event is actually a message-trap.
What we are doing here is just some basic subclassing (yet another term, I'm sorry). In our case that means that we try to rewrite the resize message handler supplied by VB (UserControl_Resize). But we are stuck if no message at all is sent when the resizing in a particular direction takes place (the directions that we still cannot handle). But then again, how can a window resize if it doesn't get a message (it cannot, believe me) so we'll search further and we will find the right message to handle for this particular case. A message that surprisingly doesn't trap the Resize event, which it should, but hey, that's the bug we're solving, right?
There's something else I'd like to ask. Since your matter is addressed in Q171478 in the knowledge base, and since microsoft says to have fixed the problem in VS97SP2, I think it's a good idea to try again to install the service pack. Maybe something went wrong while you did it previously? You may want to look up that article on msdn.microsoft.com, so you can check to see if it's the same issue.
Abel
abel > Can you go back to that code and get it to work again?
Have you done this already? You didn't mention it anymore
ramses > but the eternal calling still happens.
Can you remove the commented code and post a cleansed copy here? Test it again after you have cleansed it and then post it, please. Make that a copy of *all* your code (like my original code-posting).
ramses > I could get hands on Crazy Bytes Cd's
Be careful with statements like that on EE. In europe, there's a manhunt going on after people selling CB cd's and the like and they succeed more often lately. Also, it is illegal to trade on EE, read the guidelines.
ramses > pretty strange for an empty usercontrol huh?
No, a WM_PAINT is *always* sent. But what I don't get is why that is causing a recursive loop. You don't handle the WM_PAINT, do you?
ramses > Are callbacks for the WindowMessages the only things that get fired upon resizing a control?
You might want to read something about windows, messages and callbacks. An unmissable book on the shelf when you work with these and VB is "Visual Basic Programming Guide To The Win32 API" by the famous Dan Appleman. You might be able to get an old copy of the book for little money. The first edition was written for VB4 but that shouldn't really be a matter.
But you want an answer, I guess, not some moralistic propaganda. The answer is "yes and no". Callbacks are not fired and you can put as many of them in a line as you like (but this is very dangerous). At this moment we are subclassing the control, but we could also hook it. But that would only complicate the matter and wouldn't give us any more possibilities. "Firing" is a VB-thing and something that large companies do. Windows "sends" messages to get things done, like WM_CREATE to create a window, WM_DESTROY to destroy a window or WM_MOVE to move a window. Try it out with SendMessage, you'll be surprised of the many posibilities.
In short: callbacks don't get fired, in VB-terms, messages get fired, in fact, an event is actually a message-trap.
What we are doing here is just some basic subclassing (yet another term, I'm sorry). In our case that means that we try to rewrite the resize message handler supplied by VB (UserControl_Resize). But we are stuck if no message at all is sent when the resizing in a particular direction takes place (the directions that we still cannot handle). But then again, how can a window resize if it doesn't get a message (it cannot, believe me) so we'll search further and we will find the right message to handle for this particular case. A message that surprisingly doesn't trap the Resize event, which it should, but hey, that's the bug we're solving, right?
There's something else I'd like to ask. Since your matter is addressed in Q171478 in the knowledge base, and since microsoft says to have fixed the problem in VS97SP2, I think it's a good idea to try again to install the service pack. Maybe something went wrong while you did it previously? You may want to look up that article on msdn.microsoft.com, so you can check to see if it's the same issue.
Abel
ASKER
Abel,
You?ve asked quite a few questions. I?ll address each of them, but out of order.
First of all, the Service Packs (SP) are meant for the real versions of the programming language (PL). The ones where you have to pay for. The SP?s don?t recognize Visual Basic Control Creation Edition (VBCCE) as a PL to be updated, so all I can do with the SP?s is update (manually) the controls that where shipped with VBCCE.
Because you insist, I?ll try again to install SP2, but my hopes are not so high.
Can I go back to that code and get it to work again?
I?ll try, but I?m not sure. We?ve changed so many things.
I?ll remove all commented code and post a ?cleansed? copy here.
My remark about the CB?s wasn?t meant for real, just, how do you call it, ironic (I?m not sure about that word). Anyway, I was just kidding.
ramses > pretty strange for an empty usercontrol huh?
I meant: ?Isn?t it strange that the WM_PAINT is being called OVER AND OVER AGAIN on an empty Usercontrol (UC)? No, I don?t handle the WM_PAINT, just WM_WINDOWPOSCHANGED and WM_MOVE
?But we are stuck if no message at all is sent when the resizing in a particular direction takes place? Messages are being send when dragging EACH handle to resize the UC, but the messages that are being send are not the same for each handle
This is the ?cleansed? code
MODULE 1
Option Explicit
Global gUserCtl As UserControl1
Global Const WM_WINDOWPOSCHANGED = &H47
Private Const GWL_WNDPROC = -4
Private Const WM_GETMINMAXINFO = &H24
Private Const WM_MOVE = &H3
Private Const WM_SIZE = &H5
Private Const WM_PAINT = &HF
Private Const WM_ERASEBKGND = &H14
Private Const WM_SETCURSOR = &H20
Private Const WM_MOUSEACTIVATE = &H21
Private Const WM_WINDOWPOSCHANGING = &H46
Private Const WM_NCCALCSIZE = &H83
Private Const WM_NCHITTEST = &H84
Private Const WM_NCPAINT = &H85
Global lpPrevWndProc As Long
Global gHW As Long
Private Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam 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
Public Sub Hook()
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Public Sub Unhook()
Dim temp As Long
temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
End Sub
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Static RecursiveMsg As Boolean
Static ScndRecursiveMsg As Boolean
On Error Resume Next
Debug.Print "Message called: " + Trim(Str(uMsg))
If Err.Number = 28 Then
Unhook
MsgBox "Stack overflow error"
Exit Function
Else
If Err <> 0 Then
Unhook
MsgBox "Other error: " + Err.Description + "(" + Trim(Str(Err.Number))
Exit Function
End If
End If
Select Case uMsg
Case WM_WINDOWPOSCHANGED
If Not RecursiveMsg Then
RecursiveMsg = True
gUserCtl.Height = 200
gUserCtl.Width = 200
RecursiveMsg = False
End If
Case WM_MOVE
If Not ScndRecursiveMsg Then
ScndRecursiveMsg = True
gUserCtl.Height = 200
gUserCtl.Width = 200
ScndRecursiveMsg = False
End If
Case Else
WindowProc = CallWindowProc(lpPrevWndPr oc, hw, uMsg, wParam, lParam)
End Select
End Function
USERCONTROL1
Option Explicit
Friend Property Let Height(newHeight As Long)
UserControl.Height = newHeight
End Property
Friend Property Get Height() As Long
Height = UserControl.Height
End Property
Friend Property Let Width(newWidth As Long)
UserControl.Width = newWidth
End Property
Friend Property Get Width() As Long
Width = UserControl.Width
End Property
Private Sub UserControl_InitProperties ()
gHW = UserControl.hwnd
Set gUserCtl = Me
Hook
End Sub
Private Sub UserControl_Show()
gHW = UserControl.hwnd
Set gUserCtl = Me
Hook
End Sub
You?ve asked quite a few questions. I?ll address each of them, but out of order.
First of all, the Service Packs (SP) are meant for the real versions of the programming language (PL). The ones where you have to pay for. The SP?s don?t recognize Visual Basic Control Creation Edition (VBCCE) as a PL to be updated, so all I can do with the SP?s is update (manually) the controls that where shipped with VBCCE.
Because you insist, I?ll try again to install SP2, but my hopes are not so high.
Can I go back to that code and get it to work again?
I?ll try, but I?m not sure. We?ve changed so many things.
I?ll remove all commented code and post a ?cleansed? copy here.
My remark about the CB?s wasn?t meant for real, just, how do you call it, ironic (I?m not sure about that word). Anyway, I was just kidding.
ramses > pretty strange for an empty usercontrol huh?
I meant: ?Isn?t it strange that the WM_PAINT is being called OVER AND OVER AGAIN on an empty Usercontrol (UC)? No, I don?t handle the WM_PAINT, just WM_WINDOWPOSCHANGED and WM_MOVE
?But we are stuck if no message at all is sent when the resizing in a particular direction takes place? Messages are being send when dragging EACH handle to resize the UC, but the messages that are being send are not the same for each handle
This is the ?cleansed? code
MODULE 1
Option Explicit
Global gUserCtl As UserControl1
Global Const WM_WINDOWPOSCHANGED = &H47
Private Const GWL_WNDPROC = -4
Private Const WM_GETMINMAXINFO = &H24
Private Const WM_MOVE = &H3
Private Const WM_SIZE = &H5
Private Const WM_PAINT = &HF
Private Const WM_ERASEBKGND = &H14
Private Const WM_SETCURSOR = &H20
Private Const WM_MOUSEACTIVATE = &H21
Private Const WM_WINDOWPOSCHANGING = &H46
Private Const WM_NCCALCSIZE = &H83
Private Const WM_NCHITTEST = &H84
Private Const WM_NCPAINT = &H85
Global lpPrevWndProc As Long
Global gHW As Long
Private Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam 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
Public Sub Hook()
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Public Sub Unhook()
Dim temp As Long
temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
End Sub
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Static RecursiveMsg As Boolean
Static ScndRecursiveMsg As Boolean
On Error Resume Next
Debug.Print "Message called: " + Trim(Str(uMsg))
If Err.Number = 28 Then
Unhook
MsgBox "Stack overflow error"
Exit Function
Else
If Err <> 0 Then
Unhook
MsgBox "Other error: " + Err.Description + "(" + Trim(Str(Err.Number))
Exit Function
End If
End If
Select Case uMsg
Case WM_WINDOWPOSCHANGED
If Not RecursiveMsg Then
RecursiveMsg = True
gUserCtl.Height = 200
gUserCtl.Width = 200
RecursiveMsg = False
End If
Case WM_MOVE
If Not ScndRecursiveMsg Then
ScndRecursiveMsg = True
gUserCtl.Height = 200
gUserCtl.Width = 200
ScndRecursiveMsg = False
End If
Case Else
WindowProc = CallWindowProc(lpPrevWndPr
End Select
End Function
USERCONTROL1
Option Explicit
Friend Property Let Height(newHeight As Long)
UserControl.Height = newHeight
End Property
Friend Property Get Height() As Long
Height = UserControl.Height
End Property
Friend Property Let Width(newWidth As Long)
UserControl.Width = newWidth
End Property
Friend Property Get Width() As Long
Width = UserControl.Width
End Property
Private Sub UserControl_InitProperties
gHW = UserControl.hwnd
Set gUserCtl = Me
Hook
End Sub
Private Sub UserControl_Show()
gHW = UserControl.hwnd
Set gUserCtl = Me
Hook
End Sub
ASKER
Sorry guys, it seems that not all characters are displayed properly... Replace ? with "
Ramses
Ramses
ASKER
I can't find the SP2 downloadpage anymore. Anyone knows?
Ramses
Ramses
> Sorry guys, it seems that not all characters
> are displayed properly... Replace ? with "
I guess you typed it in Word or WP and copied and pasted the text?
It's not SP2 anymore. I'm currently downloading SP3, but I'm on location and I don't know the SP's link by heart. I'll be back in the evening for that.
I think I might now the problem and the reason. Here's the catch:
When you first create the control you call Hook in InitProperties. The Show is fired and in that function you call Hook again. The function Hook sets the lpPrevWndProc variable, which holds a pointer to the previous window procedure. When we call it the second time, our WindowProc function *is* the current window procedure and that is set to lpPrevWndProc by the Hook function. Conclusion, lpPrevWndProc and AddressOf WindowProc point to the same function. Hence CallWindowProc calls our WindowProc and not the previous window function. Are you still with me? Good.
Now, to resolve this issue, just check the value of lpPrevWndProc before we set it in the Hook function as follows:
Public Sub Hook()
If lpPrevWndProc = 0 Then
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)
End If
End Sub
That should do the trick. The only thing that puzzles me is *why* it worked in the first place. It should have bailed out with error 28 as well.
By the way, it good that you quoted "cleansed": I hoped for a smallest working version of the code as from our first postings, but this is not it. But never mind. It is still small enough to be clear :-)
Btw2: about WM_PAINT, that was exactly what puzzled me too (see my prev. comment) :-)
Btw3: Ironic is the right word :-)
I have downloaded CCE and installed it. It works as expected: it doesn't work correctly with the resizing the way you would expect. I'm going to try to install the SP3 myself and I'll keep you posted about my findings.
Rgds,
Abel
> are displayed properly... Replace ? with "
I guess you typed it in Word or WP and copied and pasted the text?
It's not SP2 anymore. I'm currently downloading SP3, but I'm on location and I don't know the SP's link by heart. I'll be back in the evening for that.
I think I might now the problem and the reason. Here's the catch:
When you first create the control you call Hook in InitProperties. The Show is fired and in that function you call Hook again. The function Hook sets the lpPrevWndProc variable, which holds a pointer to the previous window procedure. When we call it the second time, our WindowProc function *is* the current window procedure and that is set to lpPrevWndProc by the Hook function. Conclusion, lpPrevWndProc and AddressOf WindowProc point to the same function. Hence CallWindowProc calls our WindowProc and not the previous window function. Are you still with me? Good.
Now, to resolve this issue, just check the value of lpPrevWndProc before we set it in the Hook function as follows:
Public Sub Hook()
If lpPrevWndProc = 0 Then
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)
End If
End Sub
That should do the trick. The only thing that puzzles me is *why* it worked in the first place. It should have bailed out with error 28 as well.
By the way, it good that you quoted "cleansed": I hoped for a smallest working version of the code as from our first postings, but this is not it. But never mind. It is still small enough to be clear :-)
Btw2: about WM_PAINT, that was exactly what puzzled me too (see my prev. comment) :-)
Btw3: Ironic is the right word :-)
I have downloaded CCE and installed it. It works as expected: it doesn't work correctly with the resizing the way you would expect. I'm going to try to install the SP3 myself and I'll keep you posted about my findings.
Rgds,
Abel
ASKER
Thanks Abel
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
btw: I also encountered the troublesome installation of the SP3 package. Just don't do it by hand, you'll probably just end up having more bugs then before.
Wow! Good work abel. I have no need to try it myself, but with all that work, it seems like it should be worth at least 200 points and an A-grade! ramses--when do you think you'll have that much (or whatever you think it's worth)?
ASKER
At the rate my points are increasing, I'd say in about 11 days. I get 10 points a day. Seems a bit strange but that's what happening. When I first signed up, I was under the impression that when you solve a question and the answer is accepted, you get the points that the question was, and the expert points based on the grade. How else are you supposed to get points?
Ramses
Abel, I'll try the code right away, as for the points, you'll notice an increase everyday.
Ramses
Abel, I'll try the code right away, as for the points, you'll notice an increase everyday.
ASKER
ABEL
THIS IS GREAT!
IT WORKS WITHOUT CRASHING!
NO RESIZING ALLOWED FROM ANY HANDLE!
THANKS
BTW, CAN YOU ALSO ANSWER THE QUESTION ABOVE THIS ONE PLEASE
RAMSES
THIS IS GREAT!
IT WORKS WITHOUT CRASHING!
NO RESIZING ALLOWED FROM ANY HANDLE!
THANKS
BTW, CAN YOU ALSO ANSWER THE QUESTION ABOVE THIS ONE PLEASE
RAMSES
It should be that you get 5 pts a day, at least I do. When you answer questions, the amount of the points of the question is quadrupled, tripled, doubled or stays the same and is than added added to your "expert points" score. That's a separate score that has nothing to do with your "Question points" and it cannot be used to ask questions.
Great that it worked for you too. I hope you also understood some technical details in this thread, as when it does, it sure helps a lot when solving this kind of problems. Note one of the first comments in the previous thread where I pointed out that you cannot easily use this solution when you place more than one usercontrol on the same form, or even in the same project.
Btw, the book I mentioned is really the easiest to read and the best on the subject. It starts at the beginning and ends pretty/very advanced and it advances in an easy to follow pace.
You can just accept the comment with the answer as answer by clicking "Accept comment as answer" and awarding it as soon as you think you have raised the points for this question (and the prev. thread) to its right amount. I'll leave it up to you.
Groeten van je noorderburen! :-)
Abel
Great that it worked for you too. I hope you also understood some technical details in this thread, as when it does, it sure helps a lot when solving this kind of problems. Note one of the first comments in the previous thread where I pointed out that you cannot easily use this solution when you place more than one usercontrol on the same form, or even in the same project.
Btw, the book I mentioned is really the easiest to read and the best on the subject. It starts at the beginning and ends pretty/very advanced and it advances in an easy to follow pace.
You can just accept the comment with the answer as answer by clicking "Accept comment as answer" and awarding it as soon as you think you have raised the points for this question (and the prev. thread) to its right amount. I'll leave it up to you.
Groeten van je noorderburen! :-)
Abel
ASKER
Ok Abel
Wouldn't it be better if I leave this question open until I got enough points to reward you?
Let's say we'll go to 200 points
This question's currently 90pts.
200-90=110
5pts/day
=110/5=22days
Kinda long huh?
Isn't there another way to get points, without cashflow?
Btw, the controls I make have functionallity in some way that 1 instance of them is enough. But I guess you're right. Users can put more instanses of a control on a form. So I guess I have to anticipate it. I know App.previnstance doesn't work in this case and I'll assume that if one creates another instance of the control, only the last added control's windowproc will be called. Hmm... maybe I'll try to solve this by making a list with control names, if I can access them. But what about controlarrays?
Anyway, thanks for all the help, and I'll try to work something out. Please let me know how you feel about the points-related comment in this text.
Ramses
Wouldn't it be better if I leave this question open until I got enough points to reward you?
Let's say we'll go to 200 points
This question's currently 90pts.
200-90=110
5pts/day
=110/5=22days
Kinda long huh?
Isn't there another way to get points, without cashflow?
Btw, the controls I make have functionallity in some way that 1 instance of them is enough. But I guess you're right. Users can put more instanses of a control on a form. So I guess I have to anticipate it. I know App.previnstance doesn't work in this case and I'll assume that if one creates another instance of the control, only the last added control's windowproc will be called. Hmm... maybe I'll try to solve this by making a list with control names, if I can access them. But what about controlarrays?
Anyway, thanks for all the help, and I'll try to work something out. Please let me know how you feel about the points-related comment in this text.
Ramses
ASKER
I give up for now.
This is what I expierenced
When creating another instance of the control, the WindowProc now points to the 2nd control so when messages from the first control are send, they are intercepted by the 2nd control. I have no clue whatsoever to accomplish this. Maybe I should just warn the user not to place more than one instance of the control per project?
When I think about it, I get it as follows:
memory
23239832 Usercontrol1
23239833 WindowProc
so, in the Hook procedure, you set SetWindowLong(blabla, AdresOff(WindowProc) right?
now, I don't believe it's possible that two objects reside on the same adress, since a binary bit can only be 0 or 1, not 10 or 01, so in my thougts, it should be like this
memory
23239832 Usercontrol1
23239833 WindowProc
23239834 other code
23239835 ...
23239900 Usercontrol2
23239901 WindowProc
23239902 other code
23239903 ...
So, the address that the first UC sets for the event-trap is 23239833 and the 2nd UC is 23239901 both objects have another address in memory, so they shouldn't interfere with each other? Right? Then why isn't this right? Abel, I know you suggest to read a book about it but thing is, I'm on a verry thight budget. I can't spare an ? more (Jij kunt het Euro symbool toch zien he).
Anyway, I'll come to think that "bullet-proof" should actually mean that it handles multiple instances as well. Just say it if you feel different aboout this.
Ramses
This is what I expierenced
When creating another instance of the control, the WindowProc now points to the 2nd control so when messages from the first control are send, they are intercepted by the 2nd control. I have no clue whatsoever to accomplish this. Maybe I should just warn the user not to place more than one instance of the control per project?
When I think about it, I get it as follows:
memory
23239832 Usercontrol1
23239833 WindowProc
so, in the Hook procedure, you set SetWindowLong(blabla, AdresOff(WindowProc) right?
now, I don't believe it's possible that two objects reside on the same adress, since a binary bit can only be 0 or 1, not 10 or 01, so in my thougts, it should be like this
memory
23239832 Usercontrol1
23239833 WindowProc
23239834 other code
23239835 ...
23239900 Usercontrol2
23239901 WindowProc
23239902 other code
23239903 ...
So, the address that the first UC sets for the event-trap is 23239833 and the 2nd UC is 23239901 both objects have another address in memory, so they shouldn't interfere with each other? Right? Then why isn't this right? Abel, I know you suggest to read a book about it but thing is, I'm on a verry thight budget. I can't spare an ? more (Jij kunt het Euro symbool toch zien he).
Anyway, I'll come to think that "bullet-proof" should actually mean that it handles multiple instances as well. Just say it if you feel different aboout this.
Ramses
I'll come back on Monday, then I comment on those comments, ok?
Ket eurosymbool wordt bij mij een vraagteken, dat komt denk ik door de "translator" van EE.
(The eurosymbol becomes a questionmark when I look at it, I think that's due to the "translator" of EE)
Ket eurosymbool wordt bij mij een vraagteken, dat komt denk ik door de "translator" van EE.
(The eurosymbol becomes a questionmark when I look at it, I think that's due to the "translator" of EE)
If you have a very tight budget, you should ask for more: the level of programming has steeply raised from basic to highly advanced skills, particularly when you read through the code I'm going to present you in the next comment. To give you an idea, for a similar project, that took about as long to create this code for you (some nine hours) I'd charge about 1500 to 2000 guilders, depending on the customer. So, raise your rate!
I agree that bulletproof means that it should handle multiple instances as well, but I do not agree that I didn't give you that. All that it requires is some basic programming knowledge to extend this bulletproof version to a more bulletproof version. At least, that's what I thought.
I created this kind of controls and controls-subclassing very often, but never did it with VB5CCE and since VB6 emerged I never used VB5 anymore. In a normal scenario there are two approaches:
1. Singleton
You want the users to create only one instance of your control: make it a singleton. I understand from your previous comment that you don't know how to do it and I wonder if I can. I have managed it, but it's a bit hard and irrational in VB, let alone CCE. Funny thing is, use C++/ATL or C++/MFC and it's a breeze! (where have we heard that one before...)
2. Multiple instances
To make our subclassing solution bulletproof we need three things. First, create a dynamic array of the UC class, second, make the hWnd of each control public, third, lookup the right control in the window procedure. This all is part of a well-documented bag of tricks that can be achieved in a couple of ways. I choose the one without Dictionaries or Collections and my lookup-system is plain brute-force.
In any normal situation you are done with this. I created a small test-scenario to see if I could get it to work an partially it did, but I must say that I both overlooked a few things and encountered a few more strange behaviours of CCE. I've managed to overcome all problems except one: in the final version it is not possible to alter the UC while it is sited on a form. First close the form or remove the instance(s) before editing the code. Certain changes in the code will make VB crash and in the current approach you cannot help it, nor is there a workaround (unless you're going to use a completely different approach, but I'll leave that up to you).
Before you start copying and pasting the code, I want to invite you to read the next few comments as well as they will help you when you are going to make alterations to the code presented here. It's a bag of important things to know about COM/VB/CCE and the like. I'll try to keep it simple.
1. A module is loaded once
Indeed it is. Print the address of a function in a module from several instances of you object and they will all point to the same address. You make it appear in your comment as if each object will have its own window procedure, but it has not. They all share the same window procedure and there's (almost) nothing you can do about it. Even in C++ this is almost impossible to overcome, at least not without assembler, so just don't think about it, it's not worth it. Just work with one module that is shared amongst all you UC's and all it's objects that appear in the same process.
2. All data in the module is loaded once
As above, this holds true also. A public array in a module will be loaded once. You can use this information to see if there's already an instance of your object and give an error if there is.
3. Sub Main is called once
When you configure your UC to start from sub main, that is, as follows from 1 and 2, also called once and *before* any UC is instantiated.
4. Each UC will take its datasize in memory
When you're going to read memory addresses again, remember then that each UC is loaded at a memory address and takes up as much space as is needed for all its datamembers. Its functions, even if they are many, are stored elsewhere and will not show up in the size of the UC in memory. Nevertheless, Len(UC) will always give 4: the amount of bytes needed to store a pointer, ie, the pointer to the first memory address.
5. Siting and unsiting
These are very important events, but you cannot access them without subclassing in VB. A control sites when it attaches itself to the parent and it unsites when it detaches itself. Quite a while earlier/later the initialize and terminate events are called. I use the unsite-event in the code.
6. When you run a project, the UC's are dismissed
You might expect a neat shutdown of a UC, but then part of it could stay in memory depending on how you code your component. To overcome this, VB fires the Terminate event, even if more then one reference to the UC still exist. This means that the unsite event (message) is not fired (sent) and that VB unloads the whole UC just after the Terminate event. This is unfortunate and to abrupt, but in the code this has been solved easily.
The problem was that the data-part was zeroed by VB but the executable part still existed in memory. Hence the WindowProc got called but ran into trouble, because of the zeroed data. To understand what I mean, remove the statement in the Terminate event and run the project.
7. Show event is not called when siting the first time
I've always found this ridiculous. If I'm not mistaken, this is the same in all VB versions. There's no single point of entry that you can code for the moment that the object visualizes. You at the very least have to use InitProperties and Show, of InitProperties and ReadProperties, which is a bit unintuitive, don't you think?
8. There's a lot more but I can't think of it anymore
I encountered a lot more things and a lot more advanced VB techniques (or API techniques) have been used. Probably a lot of them will go unnoticed, but who cares. It's working, isn't it?
When you read through the code, and I hope you will, I hope you understand the lot of it. Most of the stuff is pretty basic and the overall structure is kept to the simplest I could think of for this scenario. It's amazing what people do just to retain a certain size!
Regards,
Abel
I agree that bulletproof means that it should handle multiple instances as well, but I do not agree that I didn't give you that. All that it requires is some basic programming knowledge to extend this bulletproof version to a more bulletproof version. At least, that's what I thought.
I created this kind of controls and controls-subclassing very often, but never did it with VB5CCE and since VB6 emerged I never used VB5 anymore. In a normal scenario there are two approaches:
1. Singleton
You want the users to create only one instance of your control: make it a singleton. I understand from your previous comment that you don't know how to do it and I wonder if I can. I have managed it, but it's a bit hard and irrational in VB, let alone CCE. Funny thing is, use C++/ATL or C++/MFC and it's a breeze! (where have we heard that one before...)
2. Multiple instances
To make our subclassing solution bulletproof we need three things. First, create a dynamic array of the UC class, second, make the hWnd of each control public, third, lookup the right control in the window procedure. This all is part of a well-documented bag of tricks that can be achieved in a couple of ways. I choose the one without Dictionaries or Collections and my lookup-system is plain brute-force.
In any normal situation you are done with this. I created a small test-scenario to see if I could get it to work an partially it did, but I must say that I both overlooked a few things and encountered a few more strange behaviours of CCE. I've managed to overcome all problems except one: in the final version it is not possible to alter the UC while it is sited on a form. First close the form or remove the instance(s) before editing the code. Certain changes in the code will make VB crash and in the current approach you cannot help it, nor is there a workaround (unless you're going to use a completely different approach, but I'll leave that up to you).
Before you start copying and pasting the code, I want to invite you to read the next few comments as well as they will help you when you are going to make alterations to the code presented here. It's a bag of important things to know about COM/VB/CCE and the like. I'll try to keep it simple.
1. A module is loaded once
Indeed it is. Print the address of a function in a module from several instances of you object and they will all point to the same address. You make it appear in your comment as if each object will have its own window procedure, but it has not. They all share the same window procedure and there's (almost) nothing you can do about it. Even in C++ this is almost impossible to overcome, at least not without assembler, so just don't think about it, it's not worth it. Just work with one module that is shared amongst all you UC's and all it's objects that appear in the same process.
2. All data in the module is loaded once
As above, this holds true also. A public array in a module will be loaded once. You can use this information to see if there's already an instance of your object and give an error if there is.
3. Sub Main is called once
When you configure your UC to start from sub main, that is, as follows from 1 and 2, also called once and *before* any UC is instantiated.
4. Each UC will take its datasize in memory
When you're going to read memory addresses again, remember then that each UC is loaded at a memory address and takes up as much space as is needed for all its datamembers. Its functions, even if they are many, are stored elsewhere and will not show up in the size of the UC in memory. Nevertheless, Len(UC) will always give 4: the amount of bytes needed to store a pointer, ie, the pointer to the first memory address.
5. Siting and unsiting
These are very important events, but you cannot access them without subclassing in VB. A control sites when it attaches itself to the parent and it unsites when it detaches itself. Quite a while earlier/later the initialize and terminate events are called. I use the unsite-event in the code.
6. When you run a project, the UC's are dismissed
You might expect a neat shutdown of a UC, but then part of it could stay in memory depending on how you code your component. To overcome this, VB fires the Terminate event, even if more then one reference to the UC still exist. This means that the unsite event (message) is not fired (sent) and that VB unloads the whole UC just after the Terminate event. This is unfortunate and to abrupt, but in the code this has been solved easily.
The problem was that the data-part was zeroed by VB but the executable part still existed in memory. Hence the WindowProc got called but ran into trouble, because of the zeroed data. To understand what I mean, remove the statement in the Terminate event and run the project.
7. Show event is not called when siting the first time
I've always found this ridiculous. If I'm not mistaken, this is the same in all VB versions. There's no single point of entry that you can code for the moment that the object visualizes. You at the very least have to use InitProperties and Show, of InitProperties and ReadProperties, which is a bit unintuitive, don't you think?
8. There's a lot more but I can't think of it anymore
I encountered a lot more things and a lot more advanced VB techniques (or API techniques) have been used. Probably a lot of them will go unnoticed, but who cares. It's working, isn't it?
When you read through the code, and I hope you will, I hope you understand the lot of it. Most of the stuff is pretty basic and the overall structure is kept to the simplest I could think of for this scenario. It's amazing what people do just to retain a certain size!
Regards,
Abel
Here's the code. It should be self-explanatory after you read the comment above and when you read the comments in the code.
'************************* ********
'** Module part
'************************* ********
Option Explicit
Public gUserCtl() As UserControl1
Public iCtlCount As Integer
Public Const GWL_WNDPROC = -4
Public Const WM_DESTROY = &H2
Public Const WM_WINDOWPOSCHANGING = &H46
Public Const SWP_NOSIZE = &H1
Public Type WINDOWPOS
hWnd As Long
hWndInsertAfter As Long
x As Long
y As Long
cx As Long
cy As Long
flags As Long
End Type
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Sub CopyMemoryToWindowPos Lib "KERNEL32" Alias "RtlMoveMemory" (hpvDest As WINDOWPOS, ByVal hpvSource As Long, ByVal cbCopy As Long)
Private Declare Sub CopyMemoryFromWindowPos Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal hpvDest As Long, hpvSource As WINDOWPOS, ByVal cbCopy As Long)
Public Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Sub AddUserCtl(newCtl As UserControl1)
'inserts new ctl in array
Dim iCtl As Integer
Const ArrayStep As Integer = 2
If iCtlCount Mod ArrayStep = 0 Then
'increase array
ReDim Preserve gUserCtl(iCtlCount + ArrayStep)
End If
For iCtl = 0 To iCtlCount - 1
If gUserCtl(iCtl) Is newCtl Then
Exit For
End If
Next iCtl
If iCtl >= iCtlCount Then 'not found, add
Set gUserCtl(iCtlCount) = newCtl
Else 'found, do no add
'nothing to do
End If
iCtlCount = iCtlCount + 1
End Sub
Public Sub RemoveUserCtlByHwnd(hw As Long)
'Removes ctl from array and reorders array
Dim bFound As Boolean
Dim i As Integer
If iCtlCount = 0 Then
Exit Sub
End If
For i = 0 To iCtlCount - 1
If gUserCtl(i) Is Nothing Then
Exit For
End If
If Not bFound Then
bFound = gUserCtl(i).hWnd = hw
End If
If bFound Then
If gUserCtl(i).hWnd = hw Then
Set gUserCtl(i) = Nothing
End If
Set gUserCtl(i) = gUserCtl(i + 1)
End If
Next i
iCtlCount = iCtlCount - 1
End Sub
Public Function FindUserCtlByHwnd(hw As Long) As UserControl1
'look up correct userctl
Dim iCtl As Integer
For iCtl = 0 To iCtlCount - 1
If gUserCtl(iCtl) Is Nothing Then
iCtl = iCtlCount
Exit For
End If
If gUserCtl(iCtl).hWnd = hw Then
Exit For
End If
Next iCtl
Set FindUserCtlByHwnd = gUserCtl(iCtl) 'Returns Nothing if not found
End Function
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim usrCtl As UserControl1
Select Case uMsg
Case WM_WINDOWPOSCHANGING
Dim wp As WINDOWPOS
CopyMemoryToWindowPos wp, lParam, Len(wp)
If wp.cx <> 200 And wp.cy <> 200 Then
wp.flags = wp.flags Or SWP_NOSIZE
End If
CopyMemoryFromWindowPos lParam, wp, Len(wp)
Set usrCtl = FindUserCtlByHwnd(hw)
If usrCtl Is Nothing Then
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Else
WindowProc = CallWindowProc(usrCtl.OldW ndProc, hw, uMsg, wParam, lParam)
End If
Case &H100E 'Some of VB's own messages (undocumented!)
'The Terminate event does not fire because we hold a reference to it in the array
'that's why we cannot unhook in the Terminate event (it will never be called!)
'This message is the WM_VBSITE message (wp=37 means site, wp=38 means unsite) and
'is fired whenever a control is (un)sited.
If wParam = 38 Then 'UNSITE message, the visual representation of the object is
'about to be be destroyed
Set usrCtl = FindUserCtlByHwnd(hw)
If usrCtl Is Nothing Then
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Else
SetWindowLong hw, GWL_WNDPROC, usrCtl.OldWndProc
RemoveUserCtlByHwnd hw
End If
End If
Case Else
Set usrCtl = FindUserCtlByHwnd(hw)
If usrCtl Is Nothing Then
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Else
WindowProc = CallWindowProc(usrCtl.OldW ndProc, hw, uMsg, wParam, lParam)
End If
End Select
End Function
'************************* ********
'** UserControl part
'************************* ********
Option Explicit
Private lPrevWndProc As Long 'Previous window procedure for this object
Friend Property Get OldWndProc() As Long
OldWndProc = lPrevWndProc
End Property
Friend Property Get hWnd() As Long
hWnd = UserControl.hWnd
End Property
Private Sub UserControl_Click()
Debug.Print "Clicked!!!"
End Sub
Private Sub UserControl_InitProperties ()
UserControl_Resize 'Resize *before* subclassing, after that it's not allowed anymore!
AddUserCtl Me
lPrevWndProc = SetWindowLong(UserControl. hWnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Private Sub UserControl_Resize()
'Seems redundant, but is needed to show VB that the size has changed
'To understand what happens otherwise, just remove these two statements and it will clarify for you
'once you draw the object and try to resize it
Height = 400
Width = 400
End Sub
Private Sub UserControl_Show()
If lPrevWndProc = 0 Then
UserControl_Resize 'Resize *before* subclassing, after that it's not allowed anymore!
AddUserCtl Me
lPrevWndProc = SetWindowLong(UserControl. hWnd, GWL_WNDPROC, AddressOf WindowProc)
End If
End Sub
Private Sub UserControl_Terminate()
If lPrevWndProc <> 0 Then
'Sometimes Terminate is called without first sending the unsite message (see WindowProc)
'This happens ie. when you hit the run button and the object is still loaded in memory.
SetWindowLong UserControl.hWnd, GWL_WNDPROC, lPrevWndProc
End If
End Sub
'*************************
'** Module part
'*************************
Option Explicit
Public gUserCtl() As UserControl1
Public iCtlCount As Integer
Public Const GWL_WNDPROC = -4
Public Const WM_DESTROY = &H2
Public Const WM_WINDOWPOSCHANGING = &H46
Public Const SWP_NOSIZE = &H1
Public Type WINDOWPOS
hWnd As Long
hWndInsertAfter As Long
x As Long
y As Long
cx As Long
cy As Long
flags As Long
End Type
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Sub CopyMemoryToWindowPos Lib "KERNEL32" Alias "RtlMoveMemory" (hpvDest As WINDOWPOS, ByVal hpvSource As Long, ByVal cbCopy As Long)
Private Declare Sub CopyMemoryFromWindowPos Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal hpvDest As Long, hpvSource As WINDOWPOS, ByVal cbCopy As Long)
Public Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Sub AddUserCtl(newCtl As UserControl1)
'inserts new ctl in array
Dim iCtl As Integer
Const ArrayStep As Integer = 2
If iCtlCount Mod ArrayStep = 0 Then
'increase array
ReDim Preserve gUserCtl(iCtlCount + ArrayStep)
End If
For iCtl = 0 To iCtlCount - 1
If gUserCtl(iCtl) Is newCtl Then
Exit For
End If
Next iCtl
If iCtl >= iCtlCount Then 'not found, add
Set gUserCtl(iCtlCount) = newCtl
Else 'found, do no add
'nothing to do
End If
iCtlCount = iCtlCount + 1
End Sub
Public Sub RemoveUserCtlByHwnd(hw As Long)
'Removes ctl from array and reorders array
Dim bFound As Boolean
Dim i As Integer
If iCtlCount = 0 Then
Exit Sub
End If
For i = 0 To iCtlCount - 1
If gUserCtl(i) Is Nothing Then
Exit For
End If
If Not bFound Then
bFound = gUserCtl(i).hWnd = hw
End If
If bFound Then
If gUserCtl(i).hWnd = hw Then
Set gUserCtl(i) = Nothing
End If
Set gUserCtl(i) = gUserCtl(i + 1)
End If
Next i
iCtlCount = iCtlCount - 1
End Sub
Public Function FindUserCtlByHwnd(hw As Long) As UserControl1
'look up correct userctl
Dim iCtl As Integer
For iCtl = 0 To iCtlCount - 1
If gUserCtl(iCtl) Is Nothing Then
iCtl = iCtlCount
Exit For
End If
If gUserCtl(iCtl).hWnd = hw Then
Exit For
End If
Next iCtl
Set FindUserCtlByHwnd = gUserCtl(iCtl) 'Returns Nothing if not found
End Function
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim usrCtl As UserControl1
Select Case uMsg
Case WM_WINDOWPOSCHANGING
Dim wp As WINDOWPOS
CopyMemoryToWindowPos wp, lParam, Len(wp)
If wp.cx <> 200 And wp.cy <> 200 Then
wp.flags = wp.flags Or SWP_NOSIZE
End If
CopyMemoryFromWindowPos lParam, wp, Len(wp)
Set usrCtl = FindUserCtlByHwnd(hw)
If usrCtl Is Nothing Then
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Else
WindowProc = CallWindowProc(usrCtl.OldW
End If
Case &H100E 'Some of VB's own messages (undocumented!)
'The Terminate event does not fire because we hold a reference to it in the array
'that's why we cannot unhook in the Terminate event (it will never be called!)
'This message is the WM_VBSITE message (wp=37 means site, wp=38 means unsite) and
'is fired whenever a control is (un)sited.
If wParam = 38 Then 'UNSITE message, the visual representation of the object is
'about to be be destroyed
Set usrCtl = FindUserCtlByHwnd(hw)
If usrCtl Is Nothing Then
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Else
SetWindowLong hw, GWL_WNDPROC, usrCtl.OldWndProc
RemoveUserCtlByHwnd hw
End If
End If
Case Else
Set usrCtl = FindUserCtlByHwnd(hw)
If usrCtl Is Nothing Then
WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
Else
WindowProc = CallWindowProc(usrCtl.OldW
End If
End Select
End Function
'*************************
'** UserControl part
'*************************
Option Explicit
Private lPrevWndProc As Long 'Previous window procedure for this object
Friend Property Get OldWndProc() As Long
OldWndProc = lPrevWndProc
End Property
Friend Property Get hWnd() As Long
hWnd = UserControl.hWnd
End Property
Private Sub UserControl_Click()
Debug.Print "Clicked!!!"
End Sub
Private Sub UserControl_InitProperties
UserControl_Resize 'Resize *before* subclassing, after that it's not allowed anymore!
AddUserCtl Me
lPrevWndProc = SetWindowLong(UserControl.
End Sub
Private Sub UserControl_Resize()
'Seems redundant, but is needed to show VB that the size has changed
'To understand what happens otherwise, just remove these two statements and it will clarify for you
'once you draw the object and try to resize it
Height = 400
Width = 400
End Sub
Private Sub UserControl_Show()
If lPrevWndProc = 0 Then
UserControl_Resize 'Resize *before* subclassing, after that it's not allowed anymore!
AddUserCtl Me
lPrevWndProc = SetWindowLong(UserControl.
End If
End Sub
Private Sub UserControl_Terminate()
If lPrevWndProc <> 0 Then
'Sometimes Terminate is called without first sending the unsite message (see WindowProc)
'This happens ie. when you hit the run button and the object is still loaded in memory.
SetWindowLong UserControl.hWnd, GWL_WNDPROC, lPrevWndProc
End If
End Sub
Note that the code has become increasingly complex. You'll have to be very caustious altering it. Due to its complex nature it'll be also much harder to help you when things fail in the future and whenever they do and you mention it, you'll have to very specific about the circumstances and the messages the appeared.
Yet another note, I usually don't supply people on EE with copy and paste solutions, but this time has been an exception. I was intrigued by the simple question and it's hard solution and that has been your luck here.
About the points, don't worry too much about them, but I would appreciate it if you'd let this question increase to 200 pts at least, if only for people buying this PAQ: they'll have to pay for this, and a lot, don't you think?
About the 10 pts daily increase of your points, I think that's because you're a Devx member. You have applied for Knowledge Pro, either as an expert or you payd for it. The points system works a bit differently then.
Regards,
Abel
Yet another note, I usually don't supply people on EE with copy and paste solutions, but this time has been an exception. I was intrigued by the simple question and it's hard solution and that has been your luck here.
About the points, don't worry too much about them, but I would appreciate it if you'd let this question increase to 200 pts at least, if only for people buying this PAQ: they'll have to pay for this, and a lot, don't you think?
About the 10 pts daily increase of your points, I think that's because you're a Devx member. You have applied for Knowledge Pro, either as an expert or you payd for it. The points system works a bit differently then.
Regards,
Abel
ASKER
Wow, Abel
I feel kinda guilty for "sqeezing" the code from you now I know in full extend how complex it is.
Anyway, this question's worth more than 200Pts in my eyes and I will search for a solution to reward at least 500Pts. Please allow me some time to do so. In the mean time, whenever you want this question to be PAQ'ed, just let me know, the remaining points will then be posted, when I have them, in a new Question with title "Points for Abel", in this TA Off course, there's an A-grade for this question, actually, they should offer a possibility to give A+++ grades or something like that.
As for the rates, you're right, I should ask more, but often I'm forced to accept lower rates because the competition is so very hard. Especially when you have to do with so little income, one is happy to accept a job for less, then let it go because I ask to much. The live of an unemployed is far from easy and not seldon do I fear the end of the month because there's to little money to last...
Anyway, I thank you for your effort, and you will be rewarded. If, at anytime, I can help you with something, just let me know. I have no fear to post my email address here because I have some very good spam filters and I got quite good at unsubscribing spam lists.
Anyway, my address is secretaris@vep.be
With kind regards
Vriendelijke groeten van je zuiderburen!
Ramses
I feel kinda guilty for "sqeezing" the code from you now I know in full extend how complex it is.
Anyway, this question's worth more than 200Pts in my eyes and I will search for a solution to reward at least 500Pts. Please allow me some time to do so. In the mean time, whenever you want this question to be PAQ'ed, just let me know, the remaining points will then be posted, when I have them, in a new Question with title "Points for Abel", in this TA Off course, there's an A-grade for this question, actually, they should offer a possibility to give A+++ grades or something like that.
As for the rates, you're right, I should ask more, but often I'm forced to accept lower rates because the competition is so very hard. Especially when you have to do with so little income, one is happy to accept a job for less, then let it go because I ask to much. The live of an unemployed is far from easy and not seldon do I fear the end of the month because there's to little money to last...
Anyway, I thank you for your effort, and you will be rewarded. If, at anytime, I can help you with something, just let me know. I have no fear to post my email address here because I have some very good spam filters and I got quite good at unsubscribing spam lists.
Anyway, my address is secretaris@vep.be
With kind regards
Vriendelijke groeten van je zuiderburen!
Ramses
ASKER
Btw Abel, you're right about the 5Pts (not 10)
ASKER
But, while this question remains open, everyone can access it for free. At this rate it's going to take an additional (100/5=20) 20 days for this to be PAQ'ed
Ramses
Ramses
Well, I don't mind it being open. I only meant that, once it is rewarded, let it be for some points. But at the other hand I don't want you to be refrained from asking questions because you'd have to wait until you have enough points. I'm not that active on this site anymore and the points don't matter that much to me that I want you spend all of yours on a single question only because MS was too lax to provide descent software. Let's say you wait to 150 and then you reward the points, that should be enough (maybe not for the answer to the question, but at least enough for me).
Abel
Abel
Btw:
Here's a simple way to enforce singleton-like behaviour, in answer to "the controls I make have functionallity in some way that 1 instance of them is enough"
In a class (be it a UC or something else) create a static variable of it's own type. Then, in the Initialize-event you set that variable to "Me" (the object me, itself I mean) when it's nothing and when it's already something you raise an error warning that only one instance is allowed.
This trick works with any object that you create and as well in design time as in run time. It is not real "singleton" behavior, but it's close and at least you prevent people from having more then one object in there project.
Here's a simple way to enforce singleton-like behaviour, in answer to "the controls I make have functionallity in some way that 1 instance of them is enough"
In a class (be it a UC or something else) create a static variable of it's own type. Then, in the Initialize-event you set that variable to "Me" (the object me, itself I mean) when it's nothing and when it's already something you raise an error warning that only one instance is allowed.
This trick works with any object that you create and as well in design time as in run time. It is not real "singleton" behavior, but it's close and at least you prevent people from having more then one object in there project.
ASKER
Thank you Abel!
ASKER
As for your previous comment, I agree, after ten more days this question will be paq'ed with an A grade. But even when paq'ed, people can purchase it for a mere price of 15pts (10%)
Wouldn't it be better in this case that you had just explained (like just now) how to prevent multiple instances? Don't get me wrong on this, it has helped me a lot, and when manually editing the form files, one can add more instances, and I don't know if that singleton simulation will work then, so it's better to have that code, kinda not look foolish to the end-user and getting comments that his/her grandson could do better and all.
Anyway, you're right about the lazyness of microsft people and I do understand that this question has cost many people (mostly you) a lot of energy and you want people to pay a higher price for purchasing the result. I have one more question dough. When people purchase a paq, do they get the whole thread or just the answer? I mean, on many occassions (including this one), some vital information is provided in the thread, and the answer is just completing the whole. I mean, just by looking at the answer, one is not completely helped if he/she doesn't know the rest of the information that was provided in the comments. I know, I know, I often tend to ramble on and on, so I'll stop right now.
Once again, Abel, thank you very much
Ramses
Wouldn't it be better in this case that you had just explained (like just now) how to prevent multiple instances? Don't get me wrong on this, it has helped me a lot, and when manually editing the form files, one can add more instances, and I don't know if that singleton simulation will work then, so it's better to have that code, kinda not look foolish to the end-user and getting comments that his/her grandson could do better and all.
Anyway, you're right about the lazyness of microsft people and I do understand that this question has cost many people (mostly you) a lot of energy and you want people to pay a higher price for purchasing the result. I have one more question dough. When people purchase a paq, do they get the whole thread or just the answer? I mean, on many occassions (including this one), some vital information is provided in the thread, and the answer is just completing the whole. I mean, just by looking at the answer, one is not completely helped if he/she doesn't know the rest of the information that was provided in the comments. I know, I know, I often tend to ramble on and on, so I'll stop right now.
Once again, Abel, thank you very much
Ramses
Anyone buying a PAQ gets the entire discussion (although not linked questions.
To answer your other questions: how do you get more points for "free"? The answer is to become an expert with 15,000 expert points, then wait a month and if you maintain 3000 points per month you get 500 to use as needed.
Personally, I find the benefit of this when I ask questions in other topic areas since if you're getting 3000 points each month, you must know a thing or two about the current topic.
To answer your other questions: how do you get more points for "free"? The answer is to become an expert with 15,000 expert points, then wait a month and if you maintain 3000 points per month you get 500 to use as needed.
Personally, I find the benefit of this when I ask questions in other topic areas since if you're getting 3000 points each month, you must know a thing or two about the current topic.
ASKER
thanks rspahitz
rspahitz, nice to know that you're still here :-)
I have a question for you. Do you recall what happened with Otta? I think I saw you participating the discussion about him. What puzzled me was what happened (the actual q. got deleted) and what ever came over him, he was a member since '97 already.
I know it's not good to start a discussion about him here, cluttering this thread, but maybe you can lift the veil a little?
Anyway, back to the subject. I don't think it's good to make an object into a singleton unless you really need to. If there is any reason why a user might want (or: need!) to create more than one object, give them the possibility to do so. Singletons are mostly useful as an out-of-process executable COM object, for example, a central repository of data. But I'll leave the judgement of do or don't to you, of course.
There's another good book, again by Dan Appleman, that is the most authoritative on this for users of "Visual Basic: Com/ActiveX Components with Visual Basic 6". I know you're on a tight budget and that you have little to spend, but whenever you have the possibility or when you really find the need to buy a book but you can't think of any, then think of this one (or the other I mentioned earlier).
Abel
PS: Have you utilized the code already? Just curious.
I have a question for you. Do you recall what happened with Otta? I think I saw you participating the discussion about him. What puzzled me was what happened (the actual q. got deleted) and what ever came over him, he was a member since '97 already.
I know it's not good to start a discussion about him here, cluttering this thread, but maybe you can lift the veil a little?
Anyway, back to the subject. I don't think it's good to make an object into a singleton unless you really need to. If there is any reason why a user might want (or: need!) to create more than one object, give them the possibility to do so. Singletons are mostly useful as an out-of-process executable COM object, for example, a central repository of data. But I'll leave the judgement of do or don't to you, of course.
There's another good book, again by Dan Appleman, that is the most authoritative on this for users of "Visual Basic: Com/ActiveX Components with Visual Basic 6". I know you're on a tight budget and that you have little to spend, but whenever you have the possibility or when you really find the need to buy a book but you can't think of any, then think of this one (or the other I mentioned earlier).
Abel
PS: Have you utilized the code already? Just curious.
Abel, I remember Otta's name, but not the context. If you want to pursue this, drop a Q in the Expert Input area ("What ever happened to Otta?"), then put the link here if I don't get to you in a reasonable time.
Well, it's not that important. He just had its account deleted by EE because of his "alleged infractions". Let's just leave it.
ASKER
Yes Abel
I have tried the code provided by you and it does WORK, even with multiple instances.
I think I will let go of the singleton thing because even though one instance will do the trick, I've seen people use more than one instance of CommonDialog control too and I wouldn't feel right to limit that kind of functionality. But anyway, the code works GREAT! As a token of my appreciation, I intend to place your text in the aboutbox like "No-resize code by Abel" or something like that, just let me know how you feel about it...
I have put the two books you mentioned on my purchase list and in time (if I can find them in this hellhole) I will buy them, once again, Thank You!
What are "alleged infractions"?
I have tried the code provided by you and it does WORK, even with multiple instances.
I think I will let go of the singleton thing because even though one instance will do the trick, I've seen people use more than one instance of CommonDialog control too and I wouldn't feel right to limit that kind of functionality. But anyway, the code works GREAT! As a token of my appreciation, I intend to place your text in the aboutbox like "No-resize code by Abel" or something like that, just let me know how you feel about it...
I have put the two books you mentioned on my purchase list and in time (if I can find them in this hellhole) I will buy them, once again, Thank You!
What are "alleged infractions"?
> What are "alleged infractions"?
From the dictionary: "zogenaamde of beweerde schendingen/inbreuken". He didn't say of what exactly, that was also why I was curious.
> intend to place your text in the aboutbox
I'm kinda honoured :-) but I don't think anybody will understand that non-resizing is difficult and then they won't understand why my name is there for such a simple task. I don't mind you using my name, but don't feel obliged either.
Btw, I forgot something. Did you notice that I use another way of dealing with the resizing then from the original postings?
Most people use more than one commondialog control (or filelist for that matter) when they have more than one form that needs them. Of course it is not necessary, but some people probably find that easier. What is the functionality of your control that it is dubious to be a singleton or not?
Abel
From the dictionary: "zogenaamde of beweerde schendingen/inbreuken". He didn't say of what exactly, that was also why I was curious.
> intend to place your text in the aboutbox
I'm kinda honoured :-) but I don't think anybody will understand that non-resizing is difficult and then they won't understand why my name is there for such a simple task. I don't mind you using my name, but don't feel obliged either.
Btw, I forgot something. Did you notice that I use another way of dealing with the resizing then from the original postings?
Most people use more than one commondialog control (or filelist for that matter) when they have more than one form that needs them. Of course it is not necessary, but some people probably find that easier. What is the functionality of your control that it is dubious to be a singleton or not?
Abel
ASKER
They're plugins I make, not really plugins in the real meaning of the word but they are ment to provide additional functionality to another control, also made by me. To give you an example, I cannot reveil what it actuallyd does (bound by confidentiality) but I can explain it with something else
Note that you cannot compare the examples with the acutall work.
consider a calculator where you have the cpu, then you could somehow say the controls I make are the buttons for the calculator, you have one 1, one 2, one 3,... No sense in putting to 1 buttons on it. Know what I mean?
I know it sounds silly and people will definatly don't understand, comprehend that it took so much trouble to prevent resizing... maybe I should reprhase it to Sublassing provided by Abel or something like that. It's just my habbit of thanking the people who helped, with they're names in the credits. If it's too silly to describe, I could also go like this: "The author wishes to thank the following people for contributing to this project:"
Abel
...
Ramses
Note that you cannot compare the examples with the acutall work.
consider a calculator where you have the cpu, then you could somehow say the controls I make are the buttons for the calculator, you have one 1, one 2, one 3,... No sense in putting to 1 buttons on it. Know what I mean?
I know it sounds silly and people will definatly don't understand, comprehend that it took so much trouble to prevent resizing... maybe I should reprhase it to Sublassing provided by Abel or something like that. It's just my habbit of thanking the people who helped, with they're names in the credits. If it's too silly to describe, I could also go like this: "The author wishes to thank the following people for contributing to this project:"
Abel
...
Ramses
I think I understand it at least a bit, but it is vague, to say the least.
I like the "wishes to thank" version :)
Rgds,
Abel
I like the "wishes to thank" version :)
Rgds,
Abel
ASKER
Consider it done Abel. I know it's very vague, but I'm cannot reveile info regarding this because it was my clients wish, I have to respect that. Do I refer to you as Abel from DevX or just Abel?
Ramses
Ramses
I'm an Experts-Exchange member (https://www.experts-exchange.com), not a DevX member (although my company is). DevX members use usually http://knowledgexchange.devx.com, which has the same functionality as Experts-Exchange, but another look and feel (only slightly different though). You are a DevX member, aren't you?
You may use just Abel, or Abel Braaksma (full name) or Abel from Experts-Exchange. I consider all to be fine referals.
Abel
You may use just Abel, or Abel Braaksma (full name) or Abel from Experts-Exchange. I consider all to be fine referals.
Abel
ASKER
Thanks, I'll go with Abel Braaksma and a link to either devx.experts-exchange.com or www.expers-exchange.com or knowledgexchange.devx.com. Should you want a link to a particular page (your site or whatever) please let me know. If you don't want to post this information here, just send it to straight-a-software@vep.be . Spammers be warned that I have very good filters that spam the spam back to the spammer... you won't like it!
Yes, I'm a DevX member and I haven't been bother with that Pop-Up add from Pop-Off :-) because I always comein in the All Topics page (from Favorites)
Ramses
Yes, I'm a DevX member and I haven't been bother with that Pop-Up add from Pop-Off :-) because I always comein in the All Topics page (from Favorites)
Ramses
ASKER
Almost there... :-)
Yep :)
Hope it didn't refrain you from asking questions, because I wouldn't want that to happen.
Hope it didn't refrain you from asking questions, because I wouldn't want that to happen.
ASKER
I'm kinda bussy with other problems right now; I have a assignment to make a piece about the September 11th attacks (to look up as much links as possible). And since this is a world-wide covvered event, I think I'll be bussy for a while...
Ramses
Ramses
ASKER
Thanks guys... until the next question then :-)
Anyone who purchases this PAQ, please take some time to read the WHOLE thread, and the previous one. That one's a 0-Pt question, so you don't have to purchase it.
Ramses says RoOAAar!
Anyone who purchases this PAQ, please take some time to read the WHOLE thread, and the previous one. That one's a 0-Pt question, so you don't have to purchase it.
Ramses says RoOAAar!
Abel, please see https://www.experts-exchange.com/questions/21154040/Points-for-Abel.html
With kind regards
x_terminat_or_3 (Ramses)
With kind regards
x_terminat_or_3 (Ramses)
Hi Ramses,
Hmm, that question appears to be deleted. What was it about that you specifically request my attention to it? Problems with the resizing solution? Or the hooking involved?
I'll here from you,
Regards,
Abel
Hmm, that question appears to be deleted. What was it about that you specifically request my attention to it? Problems with the resizing solution? Or the hooking involved?
I'll here from you,
Regards,
Abel
Hi Abel
I just wanted to give you more pts for your help but I'm not alowed by EE....
Anyway I just wanted to know that I learned much from your help.
With kind regards
x_terminat_or_3 (Ramses)
I just wanted to give you more pts for your help but I'm not alowed by EE....
Anyway I just wanted to know that I learned much from your help.
With kind regards
x_terminat_or_3 (Ramses)
That's very kind of you. It's nice to hear every now and then that people appreciate what you do.
It has been awhile, but I can still remember the issue and the research. It has been a pleasure working with you.
Kind regards,
Abel
It has been awhile, but I can still remember the issue and the research. It has been a pleasure working with you.
Kind regards,
Abel
It has been a pleasure working with you to Abel.
Ramses
Ramses
ASKER
HELP!