Suppose to start from the custom widget described in AN03002
Now suppose that you want to specialize in this widget, that you want to extend its functionality.
you could write something like that:
Display All
in the application code if you create this widget without specifing callback:
what happens is that a widget of the type MYWIDGET is created with callback MYWIDGETSPEC_Callback. At line 11 there is a call to the MYWIDGET_GetUserData function which, in turn, calls WM_GetUserData to access the MyWidget.NumExtraBytes field, which is not yet populated at the time of this call. Then a fault occurs.
I solved this by postponing the callback assignment:
Display All
I don't know, however, if this is the right way to do it, because it presupposes knowledge of the implementation of the widget you intend to specialize and extend. This is not always true (e.g. extending TEXT widgets). in addition, in the prototype of the MYWIDGET_Create function the pfCallback paramter is provided, so it seems counterintuitive and misleading to be forced to pass NULL and then postpone the assignment of the callback.
Has Segger planned different ways to achieve this?
How should I do, in general, to extend the functionality of a custom widget?
best regards
Max
Now suppose that you want to specialize in this widget, that you want to extend its functionality.
you could write something like that:
C Source Code
- /*********************************************************************
- *
- * MYWIDGETSPEC_Callback
- */
- void MYWIDGETSPEC_Callback(WM_MESSAGE * pMsg)
- {
- MYWIDGETSPEC_Handle hWin;
- MYWIDGETSPEC_Obj MyWidgetSpec;
- hWin = pMsg->hWin;
- MYWIDGET_GetUserData(hWin, &MyWidgetSpec, sizeof(MYWIDGETSPEC_Obj));
- switch (pMsg->MsgId) {
- /* some message handler to specialize the behaviour */
- default:
- MYWIDGET_Callback(pMsg);
- }
- }
- /*********************************************************************
- *
- * MYWIDGETSPEC_GetUserData
- */
- int MYWIDGETSPEC_GetUserData(MYWIDGETSPEC_Handle hWin, void *pDest, int SizeOfBuffer)
- {
- MYWIDGETSPEC_Obj MyWidgetSpec;
- int
- NumBytes;
- U8 * pExtraBytes;
- if (SizeOfBuffer <= 0) {
- return 0;
- }
- MYWIDGET_GetUserData(hWin, &MyWidgetSpec, sizeof(MYWIDGETSPEC_Obj));
- pExtraBytes =
- (U8 *) malloc(sizeof(MYWIDGETSPEC_Obj) + MyWidgetSpec.NumExtraBytes);
- if (pExtraBytes) {
- MYWIDGET_GetUserData(hWin, pExtraBytes,
- sizeof(MYWIDGETSPEC_Obj) + MyWidgetSpec.NumExtraBytes);
- if (SizeOfBuffer >= MyWidgetSpec.NumExtraBytes) {
- NumBytes = MyWidgetSpec.NumExtraBytes;
- } else {
- NumBytes = SizeOfBuffer;
- }
- GUI_MEMCPY(pDest, pExtraBytes + sizeof(MYWIDGETSPEC_Obj), NumBytes);
- free(pExtraBytes);
- return NumBytes;
- }
- return 0;
- }
- /*********************************************************************
- *
- * MYWIDGETSPEC_SetUserData
- */
- int MYWIDGETSPEC_SetUserData(MYWIDGETSPEC_Handle hWin, void *pSrc, int SizeOfBuffer)
- {
- MYWIDGETSPEC_Obj MyWidgetSpec;
- int
- NumBytes;
- U8 * pExtraBytes;
- if (SizeOfBuffer <= 0) {
- return 1;
- }
- MYWIDGET_GetUserData(hWin, &MyWidgetSpec, sizeof(MYWIDGETSPEC_Obj));
- pExtraBytes =
- (U8 *) malloc(sizeof(MYWIDGETSPEC_Obj) + MyWidgetSpec.NumExtraBytes);
- if (pExtraBytes) {
- MYWIDGET_GetUserData(hWin, pExtraBytes,
- sizeof(MYWIDGETSPEC_Obj) + MyWidgetSpec.NumExtraBytes);
- if (SizeOfBuffer >= MyWidgetSpec.NumExtraBytes) {
- NumBytes = MyWidgetSpec.NumExtraBytes;
- } else {
- NumBytes = SizeOfBuffer;
- }
- GUI_MEMCPY(pExtraBytes + sizeof(MYWIDGETSPEC_Obj), pSrc, NumBytes);
- MYWIDGET_SetUserData(hWin, pExtraBytes,
- sizeof(MYWIDGETSPEC_Obj) + MyWidgetSpec.NumExtraBytes);
- free(pExtraBytes);
- return 0;
- }
- return 1;
- }
- /*********************************************************************
- *
- * MYWIDGETSPEC_Create
- */
- MYWIDGETSPEC_Handle MYWIDGETSPEC_Create(int x0, int y0, int xSize, int ySize,
- WM_HWIN hWinParent, U32 Style, const char *pText,
- WM_CALLBACK * pfCallback, int NumExtraBytes)
- {
- MYWIDGETSPEC_Handle hWin;
- MYWIDGETSPEC_Obj MyWidgetSpec;
- WM_CALLBACK *pfUsed;
- if (pfCallback) {
- pfUsed = pfCallback;
- } else {
- pfUsed = MYWIDGETSPEC_Callback;
- }
- MyWidgetSpec = MYWIDGETSPEC_Default;
- MyWidgetSpec.NumExtraBytes = NumExtraBytes;
- if (pText) {
- MyWidgetSpec.pText = pText;
- }
- hWin = MYWIDGET_Create(x0, y0, xSize, ySize, hWinParent, Style,
- pfUsed,
- sizeof(MYWIDGETSPEC_Obj) + NumExtraBytes);
- MYWIDGET_SetUserData(hWin, &MyWidgetSpec, sizeof(MYWIDGETSPEC_Obj));
- return hWin;
- }
in the application code if you create this widget without specifing callback:
what happens is that a widget of the type MYWIDGET is created with callback MYWIDGETSPEC_Callback. At line 11 there is a call to the MYWIDGET_GetUserData function which, in turn, calls WM_GetUserData to access the MyWidget.NumExtraBytes field, which is not yet populated at the time of this call. Then a fault occurs.
I solved this by postponing the callback assignment:
C Source Code
- /*********************************************************************
- *
- * MYWIDGETSPEC_Create
- */
- MYWIDGETSPEC_Handle MYWIDGETSPEC_Create(int x0, int y0, int xSize, int ySize,
- WM_HWIN hWinParent, U32 Style, const char *pText,
- WM_CALLBACK * pfCallback, int NumExtraBytes)
- {
- MYWIDGETSPEC_Handle hWin;
- MYWIDGETSPEC_Obj MyWidgetSpec;
- WM_CALLBACK *pfUsed;
- if (pfCallback) {
- pfUsed = pfCallback;
- } else {
- pfUsed = MYWIDGETSPEC_Callback;
- }
- MyWidgetSpec = MYWIDGETSPEC_Default;
- MyWidgetSpec.NumExtraBytes = NumExtraBytes;
- if (pText) {
- MyWidgetSpec.pText = pText;
- }
- hWin = MYWIDGET_Create(x0, y0, xSize, ySize, hWinParent, Style,
- NULL,
- sizeof(MYWIDGETSPEC_Obj) + NumExtraBytes);
- WM_SetCallback(hWin, pfUsed); /* deferred callback assignmet */
- MYWIDGET_SetUserData(hWin, &MyWidgetSpec, sizeof(MYWIDGETSPEC_Obj));
- return hWin;
- }
I don't know, however, if this is the right way to do it, because it presupposes knowledge of the implementation of the widget you intend to specialize and extend. This is not always true (e.g. extending TEXT widgets). in addition, in the prototype of the MYWIDGET_Create function the pfCallback paramter is provided, so it seems counterintuitive and misleading to be forced to pass NULL and then postpone the assignment of the callback.
Has Segger planned different ways to achieve this?
How should I do, in general, to extend the functionality of a custom widget?
best regards
Max
The post was edited 1 time, last by mastupristi ().