📄 easytab.c
字号:
#include <cvidef.h>
#if _NI_mswin32_
#include <windows.h>
#endif /* _NI_mswin32 */
#include <utility.h>
#include <userint.h>
#include "toolbox.h"
#include "easytab.h"
#define TABBUTTON_ACTIVE_EXTRA_TOP 2 /* tab is made larger when active */
#define TABBUTTON_ACTIVE_EXTRA_LEFT 2
#define TABBUTTON_ACTIVE_EXTRA_RIGHT 2
#define TABBUTTON_LEFT_MARGIN 6
#define TABBUTTON_RIGHT_MARGIN 6
#define TABBUTTON_TOP_MARGIN 3
#define TABBUTTON_BOTTOM_MARGIN 2
#define CLIENT_LEFT_FRAME_WIDTH 1
#define CLIENT_RIGHT_FRAME_WIDTH 2
#define CLIENT_TOP_FRAME_WIDTH 1
#define CLIENT_BOTTOM_FRAME_WIDTH 2
#define CLIENT_VERTICAL_FRAME_WIDTH (CLIENT_TOP_FRAME_WIDTH + CLIENT_BOTTOM_FRAME_WIDTH)
#define CLIENT_HORIZONTAL_FRAME_WIDTH (CLIENT_LEFT_FRAME_WIDTH + CLIENT_RIGHT_FRAME_WIDTH)
#define CLIENT_MIN_WIDTH 1
#define CLIENT_MIN_HEIGHT 1
#define EASY_TAB_SIGNATURE CAT4CHARS('T', 'G', 'R', 'P')
#define SHEET_SIGNATURE CAT4CHARS('S', 'H', 'E', 'T')
#define TAB_BUTTON_SIGNATURE CAT4CHARS('T', 'B', 'U', 'T')
#define THREAD_SLEEP_TIME 10L
#define ATTR_EASY_TAB_OVERRIDE_CTRL_ACTIVATION_POLICY 13000
typedef struct /* for virtual tab-order lists */
{
int panel; /* panel of the control */
int ctrl; /* a control in the tab list */
int isTabStop; /* TRUE if this control can be tabbed to */
} TabOrderEntry;
typedef struct TabButtonStruct /* object which represent the visual appearance of a tab button */
{
int signature; /* debugging aid */
struct SheetStruct *sheet; /* the sheet that owns this tab button */
char *label; /* CString that holds the given text for the buttons label */
char *displayLabel; /* CString that holds the display text for the buttons label (same as label except double underlines have been removed) */
Point labelSize; /* the width of the text in pixels given the owning groups current font */
Point minSize; /* the minimum height and width the tab button can have given its label text and font */
Rect activeBounds; /* in canvas coordinates */
Rect inactiveBounds; /* in canvas coordinates */
char acceleratorKey; /* 0 if button does not have an underline accelerator */
int underlineOffset; /* number of pixels from the start of the displayed label to the start of the accelerator underline */
int underlineWidth; /* how wide the accelerator underline is in pixels */
int bitmap; /* bitmap image of text */
int dimmed; /* true if dimmed */
int tabColor; /* the color of the tab */
} *TabButton;
typedef struct SheetStruct /* object which represents a tab sheet in a tab group */
{
int signature; /* debugging aid */
int panel; /* panel that holds the controls, may be same as dialog panel */
int ownsPanel; /* TRUE if the sheet owns a child panel that contains the sheets controls */
TabButton tabButton; /* the tab button for this sheet */
int originalRow; /* which row is the tab on (1-based, starting from the top) */
struct TabGroupStruct *group; /* owner of this sheet */
ListType ctrlList; /* controls on this sheet if ownsPanel == FALSE */
int activatePanelWhenShown; /* if TRUE, the panel of this sheet is activated the next time the group is redrawn, used to postpone panel activation since it can cause premature drawing */
int originalWidth; /* width of the panel when it was added to the group */
int originalHeight; /* height of the panel when it was added to the group */
int hidden; /* true if button for sheet is to be hidden */
} *Sheet;
typedef struct TabGroupStruct /* object which represents a group of tab sheets */
{
int signature; /* debugging aid */
int dialogPanel; /* panel on which this tab dialog lives */
struct SheetStruct *activeSheet; /* which sheet is the active sheet */
ListType sheetList; /* list of sheets in this tab dialog */
ListType rowLists; /* list of lists of sheets on each row (currently displayed rows, not the rows the sheets were created on) */
int canvas; /* canvas to draw tab buttons on */
Rect originalCanvasRect; /* rect of the canvas when it was converted to a tab ctrl */
Rect frameRect; /* client area frame bounding box in panel coordinates (surrounds the client area) */
Rect clientRect; /* dialog area in panel coordinates, tab buttons appear above this */
Rect exteriorRect; /* canvas area in panel coordinates, dialog area, frame, and tab buttons appear within this */
int sizeButtonsToFillRows; /* if TRUE, buttons stretch to fit all the available space */
int tabButtonPositionsCalculated; /* if FALSE, the tab button sizes need to be calculated */
int canvasSetup; /* if FALSE, the canvas needs to be sized, etc.. */
Rect tabButtonBoundsUnion; /* in canvas coordinates */
Rect tabButtonEraseArea; /* same as tabButtonBoundsUnion, with a little extra to account for the widening of buttons when they become active */
int displayInvalidated; /* if TRUE, the group is waiting for a pending deferred callback which was posted in to redraw the group */
int textColor; /* color of the text in the Tab buttons (RGB) */
int sizeHasBeenSet; /* TRUE if the size of the tab group has ever been explicitly set. */
int buttonPosition; /* indicates where the tab buttons are in relation to the client area */
int buttonGap; /* gap between tab buttons (-1 means use a much gap as possible if sizeButtonsToFillRows is TRUE) */
char metaFont[256]; /* the font used to draw the text on the tab buttons */
int hidden; /* TRUE if the entire tab control is hidden */
int bgColor; /* color for background of tabGroup (defaults to the panel background color of the panel holding the tabGroup ctrl),
VAL_TRANSPARENT is the only other "reasonable" value, but it makes drawing slower */
int valid; /* Tells if the lock is good. */
int lockHandle;
int overrideActivation; /* if TRUE, easytab never activates the first control when switching tabs */
} *TabGroup;
/* Add thread local variables here */
typedef struct
{
int bitmapPanel;
int bitmapCanvas;
int ctrlWasClicked;
} threadLocalVars;
static TabButton TabButton_Create(Sheet sheet, const char *label);
static void TabButton_Dispose(TabButton tabButton);
static void TabButton_GetMinBounds(TabButton tabButton, int active, Rect *r);
static void TabButton_SetBounds(TabButton tabButton, Rect r);
static int TabButton_SetLabel(TabButton tabButton, const char *label);
static void TabButton_Draw(TabButton tabButton, int drawActive, int drawFocus);
static void TabButton_DrawText(TabButton tabButton, int panel, int canvas, Point textPosition);
static void TabButton_DrawLabel(TabButton tabButton, Rect bounds);
static int TabButton_HasFocus(TabButton tabButton);
static int TabButton_CreateTextBitmap(TabButton tabButton);
static int TabButton_GetTextCanvas(int *panel, int *canvas, Point size);
static int Sheet_Create(TabGroup group, int sheetPanel, int row, const char *label, ListType ctrlList, Sheet *sheet);
static void Sheet_Dispose(Sheet sheet);
static void Sheet_Remove(Sheet sheet);
static void Sheet_ActivateFirstCtrl(Sheet sheet);
static int CVICALLBACK Sheet_PanelCallback (int panel, int event, void *callbackData, int eventData1, int eventData2);
static int EasyTab_CreateFromCanvas(int panel, int canvas);
static void EasyTab_Dispose(TabGroup group, int disposeCanvas);
static Sheet EasyTab_IndexToSheet(TabGroup group, int index);
static int EasyTab_SheetToIndex(TabGroup group, Sheet sheet);
static Sheet EasyTab_PanelToSheet(TabGroup group, int panel);
static int EasyTab_NumSheets(TabGroup sheetGroup);
static int EasyTab_CalculateTabSizes(TabGroup group);
static void EasyTab_FreeRowLists(TabGroup group);
static int EasyTab_CalculateNumRows(TabGroup group);
static int EasyTab_IdToGroup(int panel, int groupCanvas, TabGroup *group);
static int CVICALLBACK EasyTab_CanvasCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2);
static int CVICALLBACK EasyTab_PanelCallback (int panel, int event, void *callbackData, int eventData1, int eventData2);
static Sheet EasyTab_GetActive(TabGroup sheetGroup);
static void EasyTab_ActivateHorizontalNeighbor(TabGroup group, int previous, int wrap);
static void EasyTab_ActivateVerticalNeighbor(TabGroup group);
static void EasyTab_SetActive(TabGroup group, Sheet activeSheet);
static int EasyTab_Draw(TabGroup group);
static void EasyTab_DrawTabButtons(TabGroup group);
static int EasyTab_HasFocus(TabGroup group);
static void EasyTab_SetFocus(TabGroup group);
static Rect EasyTab_CtrlsBoundsUnion(TabGroup group);
static Rect EasyTab_PanelBoundsUnion(TabGroup group, int sizeOnly, int useOriginalPanelSizes);
static int EasyTab_SetClientRect(TabGroup group, Rect clientRect);
static Rect EasyTab_GetClientRect(TabGroup group);
static Rect EasyTab_GetExteriorRect(TabGroup group);
static int EasyTab_SetExteriorRect(TabGroup group, Rect exteriorRect);
static void CVICALLBACK EasyTab_UpdateDisplay(void *callbackData);
static void EasyTab_InvalDisplay(TabGroup group);
static void EasyTab_InvalRowLists(TabGroup group);
static void EasyTab_InvalTabPositions(TabGroup group);
static void EasyTab_InvalAll(TabGroup group);
static void EasyTab_InvalCanvasSetup(TabGroup group);
static ListType EasyTab_GetRowLists(TabGroup group);
static void EasyTab_SetupCanvas(TabGroup group);
static int EasyTab_CalcMinButtonArea(TabGroup group, int *minHeight, int *minWidth);
static TabButton EasyTab_TabButtonAtPoint(TabGroup group, Point p);
static void EasyTab_HandleLeftClick(TabGroup group, Point p);
static void EasyTab_DrawFrame(TabGroup group);
static int EasyTab_CalculateMinClientWidth(TabGroup group, int *minWidth);
static Rect EasyTab_GetAutoSizeRect(TabGroup group, int makeRoomForButtons);
static int EasyTab_HandleNavigationKeys(TabGroup group, int key, int *callbackReturnVal);
static int EasyTab_HandleAcceleratorKey(int key, int *callbackReturnVal);
static Sheet EasyTab_AccelKeyToSheet(TabGroup group, int key);
static int EasyTab_AddSheetFromParmInfo(int panel, int easyTabCtrl, const char *sheetName, void *module, int row, int numCtrls, va_list parmInfo);
static void EasyTab_SetTextColorToDefault(TabGroup group);
static int EasyTab_CheckButtonPosition(int buttonPosition);
static int EasyTab_ResetLabels(TabGroup group);
static int EasyTab_GetSheetDisplayPosition(TabGroup group, Sheet sheet, int *row, int *column);
static void EasyTab_MoveActiveRowToEnd(TabGroup group);
static void EasyTab_InvalDisplayForPanel(int panel);
static Sheet EasyTab_GetVisibleInactiveSheet(TabGroup group);
static int EasyTab_SetInactive(TabGroup group, Sheet sheet);
static int EasyTab_NumVisibleTabsOnRow(TabGroup group, int rowIndex);
static int EasyTab_CtrlCanBeTabStop(int panel, int ctrl);
static ListType GetVirtualTabOrder(int panel, int tabGroupsOnly);
static int AddToVirtualTabOrder(int panel, ListType list, int tabGroupsOnly);
static int HandleTabKey(int key, int *callbackReturnVal);
static int GetVirtualTabTopLevelPanel(int panel);
static int NextVirtualTabStop(int panel, int ctrl, int tabbingForward, int wrap, TabOrderEntry *entry);
static void InstallActivationHooks(int panel, int install);
static void DrawRectFrameWithFill(int panel, int canvas, Rect r);
static int CreateTransparentOneColorBitmap(int *pixels, int color, int height, int width, int *bitmap);
static int RotatePixels90Degrees(int **pixels, int *height, int *width, int rotateLeft);
static int IsSheetPanel(int panel) ;
static void CVIFUNC InitializeMultithreadingIfNecessary(void);
static void CVIANSI UninitializeMultithreadingProcedure(void);
static int gThreadLocalHandle = 0;
/*************************************************************/
static void CVIFUNC InitializeMultithreadingIfNecessary(void)
{
static int sMultithreadingInitDone = 0; /* Multithreading has already been initialized */
static int sMultithreadingInitNow = 0; /* Thread local is currently being initialized. */
int prev = 0;
/* Check if already been initialized, if not, do so now. */
if (!sMultithreadingInitDone)
{
prev = InterlockedExchange(&sMultithreadingInitNow, 1);
if (prev) /* If it is initialized or is in the process of initializing. */
{
while (!sMultithreadingInitDone) /* Wait until the thread initializing the multithreading finishes */
Sleep(THREAD_SLEEP_TIME);
}
else
{
CmtNewThreadLocalVar (sizeof(threadLocalVars),
(void *)NULL, NULL, NULL,
&gThreadLocalHandle);
atexit(UninitializeMultithreadingProcedure);
sMultithreadingInitDone = 1;
}
}
}
/*************************************************************/
static void CVIANSI UninitializeMultithreadingProcedure(void)
{
/* This function used to call CmtDiscardThreadLocalVar.
That is a problem: This may be in a DLL which is being dynamically
unloaded by a program. We also added the check for
CVIRTEHasBeenDetached, which is a new function in CVI 5.0.
*/
if (!CVIRTEHasBeenDetached())
{
if (gThreadLocalHandle)
CmtDiscardThreadLocalVar (gThreadLocalHandle);
}
}
/*************************************************************/
static void FreeListOfLists(ListType listOfLists)
{
int index;
ListType list;
int numLists;
if (listOfLists)
{
numLists = ListNumItems(listOfLists);
for (index = 1; index <= numLists; index++)
{
ListGetItem(listOfLists, &list, index);
ListDispose(list);
}
ListDispose(listOfLists);
}
}
/*************************************************************/
static void EasyTab_InvalRowLists(TabGroup group)
{
EasyTab_FreeRowLists(group);
}
/*************************************************************/
static void EasyTab_FreeRowLists(TabGroup group)
{
FreeListOfLists(group->rowLists);
group->rowLists = NULL;
}
/*************************************************************/
static int EasyTab_CalculateNumRows(TabGroup group)
{
int index;
int numSheets;
int numRows = 0;
Sheet sheet;
numSheets = EasyTab_NumSheets(group);
for (index = 1; index <= numSheets; index++)
{
ListGetItem(group->sheetList, &sheet, index);
numRows = Max(numRows, sheet->originalRow);
}
return numRows;
}
/*************************************************************/
/* Build a list of lists of the sheets in each tab button row. The row member
of a sheet determines its row, and its order in the groups sheet lists
determines its order respect to other sheets in the same row.
Note: The active row (if any) is alway moved to the end of the list so it
appears at the bottom.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -