changing "Tab Control" color - ms-access

How can I change the background color of a Tab Control. I changed the forms color, but the tabs stay the same.
Thanks.

Check the Back Style of the Tab Control. If it's Normal. you'll get a gray background (with normal Windows settings). If it's Transparent then it will inherit the background colour of the form.
If you want it to be an entirely different colour, you might have to add a rectangle to the form (make the background non-transparent), maximise it within the tab and then set the colour of the rectangle.
As for the tabs them selves, I don't see a way of setting their colour independently.

As far as I know, in Access 2000/2002/2003 it's impossible to change neither background, not foreground colors of the tabs.
So, if you want to change the appearance of entire tab control, I think you are out of luck.
However, if your real goal is to implement some sort of color-coding of a tab control's pages, here is what I did when I had this problem:
I placed a colored rectangle on each page of the tab control to provide different background colors for different pages.
As for tabs themselves. Fortunately they can contain images, so I created trivial image files, each of which was a small colored bullet (square, rectangle, circle - whatever looks nicer to you) and placed them on tabs, next to text labels.
Thus, the entire control still remained grey (or whatever is the current "button color" in the Windows's current theme), but each tab and each page got associated with whatever colors I needed them to have.

With Access 2010, setting the color of the "Pressed Color" property in a tab control object allows you to set the background color of a tab page.
With Access 2013, also setting the color of the "Back Color" property for the tab control (to the same color as the "Pressed Color") was necessary.

CodeSlave made the very good suggestion:
If you want it to be an entirely
different colour, you might have to
add a rectangle to the form (make the
background non-transparent), maximise
it within the tab and then set the
colour of the rectangle.
If you want to have a background that is larger in relation to the tab dimensions than the tab allows (there is a hard border that can't be exceeded), there is another solution (though it's somewhat more complicated -- which is what usually happens when you are tweaking appearance to not work the way your default environment is designed to work).
Set the tab control to transparent. Behind the tab, place a non-transparent box. Then in the OnChange event of the tab, change the background color of the box behind the tab.
Kinda messy, yes, but it allows you to have a background that is as large as the whole tab (or larger still, in the event that you might want items off the tab inside the same color field).

You can mock this up with a little code. Set the the Style property to None for the tab control and the use any other control that has a click event to create your own colourful tabs (you can even have images). Your code can either change tabs, or change the contents of a subform.
Change tab:
Me.NameOfTabControlPage.SetFocus
Change subform control contents:
Me.NameOfSubformControl.SourceObject = "NameOfSuitableForm"

I have developed a subroutine to set the small rectangle at the right of the tabs to transparent. I tested it with Access 2003 and 2007.
Private Const GWL_EXSTYLE = -20
Private Const WS_EX_TRANSPARENT = &H20&
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 FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Public Sub PatchTabControl(ByVal f As Form)
Dim hwnd As Long
hwnd = FindWindowEx(f.hwnd, 0, "OFormSub", vbNullString)
If hwnd = 0 Then Exit Sub
hwnd = FindWindowEx(f.hwnd, hwnd, "OFormSub", vbNullString)
If hwnd = 0 Then Exit Sub
hwnd = FindWindowEx(hwnd, 0, "OTabControl", vbNullString)
If hwnd = 0 Then Exit Sub
SetWindowLong hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) Or WS_EX_TRANSPARENT
End Sub

Extending Duane Rochelle's helpful answer for Access 2010:
The problem seems to be that the names that Microsoft has given the properties that control the tab colours are contra-intuitive.
Basically, the color of the tabs can be controlled using the Pressed Color property. Look for it in the properties of the entire tab object, not the properties of individual tabs.
This means, setting Pressed Color to - for example - some kind of blue (say, #8EA3BD) makes all tabs blue. Since "pressed" means actually "the tab area is on top of the other tabs", this is more or less equivalent to colouring the tab area.
(For me personally, "Pressed Color" is a misleading name. Of all tabs in a tab object, one is visible by default, even without anybody having "pressed" a tab. A better name would be "Background color of visible tab".)
For the other elements of a tab object that one would like to paint:
For the colour of the text on the tab head (where you click to select the tab), use the Pressed Fore Color property.
For the background colour of tabs that are not visible (or "hidden behind the currently open tab"), use the Back Color property.
For text on the heads of hidden tabs, use the Fore Color property.
Accordingly, I would find the following names more intuitive:
Background color of visible tab (now "Pressed Color")
Text color of visible tab (now "Pressed Fore Color")
Background color of hidden tab (now "Back Color")
Text color of hidden tab (now "Fore Color")

Related

Microsoft Access how to stop scrolled text field from returning to top (like scroll-to-top) upon losing focus

I'm using Access 2016 in Win 10, everything updated and current. I have a form with a standard Access TextBox with a vertical scrollbar. All is fine unless I scroll down then click off the field to read info from another source or whatever because the scrolled text rolls right back to the top and I have to scroll back down to where I was before I can resume work. It wastes time and derails my train of thought.
I see no property or method to lock the 'caret' or otherwise disable this annoying behavior. I have also researched everywhere I can think of and no one seems to know what to do about it.
I've even built my own scroll buttons which worked great except it got complicated trying to keep track of the text position if I added or deleted text. So, if someone has a good custom scrollbar in VBA/VB6 I'd love to see it, please.
Thanks for your time and advice. I appreciate it.
Kent in KC.
Set and restore the selected position:
Option Compare Database
Option Explicit
Private LastPosition As Long
Private Sub YourTextbox_LostFocus()
LastPosition = Me!YourTextbox.SelStart
End Sub
Private Sub YourTextbox_GotFocus()
Me!YourTextbox.SelStart = LastPosition
Me!YourTextbox.SelLength = 0
End Sub
Private Sub Form_Current()
' Reset last position.
LastPosition = 0
End Sub
It will scroll the textbox to make the line when left to the top line visible.

How can I conditionally format textbox border on continuous form?

In Access 2010, I have a continuous form, and I'd like to change certain properties of a 'cell', like border colour, based on values in another cell. I haven't found a way to do this in VBA, because it's a continuous form and changing the properties directly in VBA changes it for all records, not just the one I'm on. I assume I have to use some form of conditional formatting, but the conditional formatting GUI only allows me to set background colour, basic text formatting, and the Enabled property.
How can I set other properties on a control on a continuous form, for specific records only?
Feeding back how I got around this problem in the end. txtFixMax is the control I wanted to give a funky border to (dependent on a value in field [ChangedToday]). It already has conditional formatting to change the background colour.
I created a second control, txtFixMaxOverlay, made it into a small square and placed it on top of the control txtFixMax. I set the properties of txtFixMaxOverlay to remove borders, and gave it the same conditional formatting as txtFixMax, so that it was invisible to the eye (but the Visible property = true). Then I gave it additional condition, the first one on the list, based on [ChangedToday], to change its background colour.
The effect isn't a border (although with a lot of tedious positioning of 4 controls I could have done this to give a border effect), but it does give me an extra element to visually change. The effect is:
You can't. Use background or text color.
See also https://msdn.microsoft.com/en-us/library/office/ff821010.aspx - there is only BackColor and ForeColor.
Yes, you can... just not with the built-in conditional formatting functionality. Use the Paint event of the Form's Detail section. There are still various limitations, but at the least you can set more properties than just the background and foreground colors.
Example:
Private Sub Detail_Paint()
If Me.IndicatorColumn.Value = "Critical" Then
Detail.BackColor = RGB(255,0,0)
Detail.AlternateBackColor = Detail.BackColor
Me.AnotherColumn.BorderStyle = 7 'Dash Dot Dot
Me.AnotherColumn.BorderColor = vbMagenta
Else
Detail.BackColor = vbWhite
Detail.AlternateBackColor = RGB(150, 150, 150)
Me.AnotherColumn.BorderStyle = 0 'Transparent
Me.AnotherColumn.BorderColor = vbWhite
End If
End Sub
See TextBox.BorderStyle.

Type Mismatch when trying to change background color through an event in Ms Access

I have a simple button in MS Access form that I require to have the background color changed and remain once the button is pressed and the mouse is no longer hovering. So, Blue static, Green on Hover, Red once pressed and remains red. I have the hover and press controls set and all work fine. But I get a mismatch error when trying to change the backcolor during the procedure.
Private Sub OpenBtn_Click()
OpenBtn.BackColor = "#ED1C24"
DoCmd.OpenForm "Customer"
End Sub
I Know I'm not using the write ' or " or & somewhere... any help is greatly appreciated.
Color is not string, you need to provide Long for BackColor. Use RGB function:
OpenBtn.BackColor = RGB(255, 0, 0) 'red color

Can I hide the ToolTipText for a Slider Bar?

In VBA programming, is it possible to hide the ToolTipText for a Slider Bar?
The picture below shows a Slider Bar on a form in a Microsoft Access database. I would like to hide the ToolTipText in the red circle.
The reason I want to do this is because the Slider Bar cannot show decimal values (example: 0,1), so I want to display the values in a box next to the slider after they are scaled to decimal values. I know how to do this, but not how to hide the ToolTipText for the Slider that shows only integer values.
There is no easy way to remove that indicator as it's not exposed through the control itself.
However, there are a couple of solutions:
Subclassing the control and intercepting Windows messages
Not for the faint of heart, complex and overkill, but you theoretically could intercept windows messages and drop those that correspond to the tooltip.
This is not easy in VBA at all, and I wouldn't even try it.
If you feel like delving into this, have a look at an example in KB278379
Just display something else.
More interesting is the ability to change the displayed text to something else:
To change the text, handle the Scroll event and update the slider's Text property:
Private Sub MySlider_Scroll()
MySlider.Text = "Awesomeness: " & (MySlider.Value * 7.89)
End Sub
The event is not visible from the control's properties themselves, but if you open the IDE and select the Slider from the list of controls, you will be able to create the code for handling the Scroll event:

How can I find the width of the parent window in MS-Access

I'm trying to force an MS-Access form to take a certain position relative to the right edge of the main window (actually I want to center it, but I can see also wanting to dock it to one side or another). I can reposition the form this with Me.Move, e.g.,
Me.Move newWindowLeft, newWindowTop, newWidth, newHeight
However, how can I find out how wide the parent window is?
You can use a windows API:
(UPDATED to return twips)
Type Rect
x1 As Long
y1 As Long
x2 As Long
y2 As Long
End Type
Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As Rect) As Long
Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Const LOGPIXELSX = 88
Const LOGPIXELSY = 90
Const DIRECTION_VERTICAL = 1
Const DIRECTION_HORIZONTAL = 0
Public Function GetMainWindowSize()
Dim MDIRect As Rect
Dim lWidthPixels As Long
Dim lWidthTwips As Long
' Get the screen coordinates and window size of the MDIClient area'
GetClientRect Application.hWndAccessApp, MDIRect
lWidthPixels = MDIRect.x2 - MDIRect.x1
lWidthTwips = PixelsToTwips(lWidthPixels, DIRECTION_HORIZONTAL)
MsgBox "Width (Pixels) = " & lWidthPixels & " Width (Twips) = " & lWidthTwips
End Function
Function PixelsToTwips(lPixels As Long, lDirection As Long) As Long
Dim lDeviceHandle As Long
Dim lPixelsPerInch As Long
lDeviceHandle = GetDC(0)
If lDirection = DIRECTION_HORIZONTAL Then
lPixelsPerInch = GetDeviceCaps(lDeviceHandle, LOGPIXELSX)
Else
lPixelsPerInch = GetDeviceCaps(lDeviceHandle, LOGPIXELSY)
End If
lDeviceHandle = ReleaseDC(0, lDeviceHandle)
PixelsToTwips = lPixels * 1440 / lPixelsPerInch
End Function
Not sure what version of Access you are using, but in Access 2003, there does not appear to be a way to directly get this information.
Here's a hack:
DoCmd.Maximize
w = Forms("yourForm").WindowWidth
h = Forms("yourForm").WindowHeight
This will maximize the current window, let's assume that it's your form. You can then measure the form to get the size of the parent window's display area, then un-maximize, and move the form based on the size of the parent window that you now know.
If there is a way to turn off ScreenUpdating in Access, you can do this before the maximize and measure code, then turn it back on, and it won't take any noticeable amount of time as far as the user is concerned.
EDIT: Even without hiding the maximize command from the user, the whole maximize and move operation happens more quickly than the user can see.
It's an ugly hack, but it does work.
I realise this is a very old question, but I want to share some code I've created to handle the desired end result of the original purpose of this question - repositioning windows so they are aligned with another existing entity.
This module exposes 3 functions:
TwipsToPixels ( _
Twips As Long, _
Optional Dimension As Dimension = DIMENSION_X _
) As Long
PixelsToTwips ( _
Pixels As Long, _
Optional Dimension As Dimension = DIMENSION_X _
) As Long
These simply convert between one unit of measurement and the other. Both accept a long integer argument input and a value from the Dimension enum, either X or Y, which can be used to specify whether the conversion should be done according the to horizontal or vertical display settings. It's worth noting that 99.99999% of the time, the value will be the same in both dimensions, so you can usually omit the second argument. Both return a long integer.
The module uses pixels for everything internally, so these conversion functions are only provided as a convenience for applications that prefer to work in twips.
PositionWindow ( _
hWnd As Long, _
Mode As PositionMode, _
Optional OffsetX As Long = 0, _
Optional OffsetY As Long = 0 _
)
hWnd is the handle of the window to be positioned (for example, to position a form window this can be obtained using objForm.hWnd).
Mode is a bit mask constructed from the options in the PositionMode enum (see below).
OffsetX is the number of pixels to adjust the position by in the horizontal dimension, after Mode has been evaluated.
OffsetY is the number of pixels to adjust the position by in the vertical dimension, after Mode has been evaluated.
Modes
Every positioning call requires an X component and a Y component. These components consist of two sub-components, a base and a position.
The base is an entity to use as a reference for calculating the new position, and can be one of DISPLAY (the active physical display on the machine), WINDOW (the main Access window) or CURSOR (the mouse pointer). For convenience, these are combined in the values from the PositionMode enum.
The active display is determined using the center pixel of the main Access window. If this falls outside the bounds of the area show on the physical displays attached to the machine, the value is adjusted to compensate, and the display with the largest visible part of the application on it will be used.
The position of the X component can be one of LEFT, RIGHT or X_CENTER. The Y component has TOP, BOTTOM and Y_CENTER.
Using LEFT causes the left-most pixel of the target window to be aligned with the left-most pixel of the base entity, and this pattern follows for RIGHT, TOP and BOTTOM. The CENTER positions cause the center-line of the target window to be aligned with the center-line of the base entity.
The values from the PositionMode enum are combined with the bitwise Or operator to achieve the desired expression.
Handling display overflow
Sometimes when WINDOW or CURSOR are used as a base for one of the components, the target window may be positioned so that some or all of it is not on a visible display. To avoid this, you can use the PREVENT_OVERFLOW_X and PREVENT_OVERFLOW_Y flags. These can simply be included in the bit mask passed to the Mode argument using the bitwise Or operator.
These flags cause the position to be adjusted, if necessary, to ensure that the entire of the target window is within the edges of the active monitor.
For convenience, a PREVENT_OVERFLOW item is also included in the enum, this is the same as specifying both PREVENT_OVERFLOW_X and PREVENT_OVERFLOW_Y.
Oveflow prevention is not applied to DISPLAY-based positions.
Offsets
The OffsetX and OffsetY arguments can be used to adjust the position of the window after it has been aligned in the manner specified by Mode. Both can be a positive or negative number, indicating a number of pixels to alter the position by in the relevant dimension.
Display overflow prevention will override offsets - the offsets will still be applied, but if the resulting position results in a portion or all of the target window being outside the active display, the position will be adjusted to bring it back inside the boundaries.
Limitations
The handling code for multiple displays makes 2 assumptions:
That the virtual display area (the combination of all displays treated as a single display) is uniform - so it won't play nice with L shaped setups or other such ridiculous configurations.
That all active displays use the same resolution.
In my experience, in the real world, these are fairly safe assumptions.
No support for simultaneously re-positioning and re-sizing is provided (as it is with objForm.Move). You will need to treat these as separate tasks.
Examples
' Get the window handle for frm_MyForm
Dim hWnd As Long
hWnd = Forms("frm_MyForm").hWnd
' Align the form to the top left corner of the active display
PositionWindow hWnd, DISPLAY_LEFT Or DISPLAY_TOP
' Align the form to the center of the Access main window
PositionWindow hWnd, WINDOW_X_CENTER Or WINDOW_Y_CENTER
' Align the form to the bottom right of the mouse pointer position, prevent the
' window from disappearing off the screen
' This effectively sets the top left corner of the window to the pointer location
PositionWindow hWnd, CURSOR_RIGHT Or CURSOR_BOTTOM Or PREVENT_OVERFLOW
' Horizontally center the form on the display, vertically center on the mouse
PositionWindow hWnd, DISPLAY_X_CENTER Or CURSOR_Y_CENTER
' Center the window on the mouse pointer then move it 200px right and 30px up
PositionWindow hWnd, CURSOR_X_CENTER Or CURSOR_Y_CENTER, 200, -30
Here's the actual code I used
Application.Echo False 'turn off screen updates
DoCmd.Maximize
w = Me.WindowWidth
h = Me.WindowHeight
DoCmd.Restore 'restore the window to it's old size
Application.Echo True 'turn on screen updates
DoCmd.MoveSize w / 2 - myWidth / 2, _
h / 2 - myHeigth / 2, _
myWidth, _
myHeigth
This may be of interest: http://www.mvps.org/access/downloads/clFormWindow.bas
It says it:
'' Moves and resizes a window in the coordinate system *
'' of its parent window. *
'' N.B.: This class was developed for use on Access forms *
'' and has not been tested for use with other window *
'' types. *