DPA_Merge

This function modifies one DPA according to the items in another DPA.

Declaration

BOOL
DPA_Merge (
    HDPA hdpaDest,
    HDPA hdpaSrc,
    DWORD dwFlags,
    PFNDPACOMPARE pfnCompare,
    PFNDPAMERGE pfnMerge,
    LPARAM lParam);

The comparison callback function has the prototype:

typedef int (*PFNDPACOMPARE) (PVOID p1, PVOID p2, LPARAM lParam);

The merge callback function has the prototype:

typedef PVOID (*PFNDPAMERGE) (UINT uMsg, LPVOID p1, LPVOID p2, LPARAM lParam);

Parameters

The hdpaDest argument provides a handle to the (target) DPA that may be modified.

The hdpaSrc argument provides a handle to the (source) DPA that provides new items.

The dwFlags argument provides bit flags to direct the behaviour. Recognised values are:

DPAM_SORTED (0x01) both input lists are already sorted
DPAM_UNION (0x04) form a generalised union of the input lists
DPAM_INTERSECT (0x08) form a generalised intersection of the input lists

The pfnCompare argument provides the address of a comparison callback function that decides the relative order of any pair of items from either DPA.

The pfnMerge argument provides the address of a merge callback function that notifies of changes to the target DPA.

The lParam argument provides a caller-specific context to be passed on each invocation of either callback function.

Return Value

The function returns TRUE for success, else FALSE.

Behaviour

The function fails trivially if either DPA handle is implausible (meaning specifically that each must be an address at which the 14h bytes of a DPA structure are writable) or if the address given for either callback function is not valid for reading at least one byte.

The function adds or removes items from the target list according to what items are found in the source list. Decisions depend on the relative order of items from each list, as defined by the combination of comparison function and context. If DPAM_SORTED is given in the dwFlags, the function assumes that both lists are already sorted in this order. Otherwise, the function sorts both lists (and merely assumes that both sort operations succeed).

The rules for modification of the target list are:

  1. If a target item is lower in order than any source item, then the target item remains in the target list.
  2. If a target item has a match among the source items, then one or the other (or a new item generated from one or the other) makes it through to the target list.
  3. If a target item (that is not lower in order than all source items) has no match among the source items, then the target item remains in the target list, except that if DPAM_INTERSECT is given among the dwFlags, the target item is deleted from the target list.
  4. If a source item has no match among the target items, then if DPAM_UNION is given among the dwFlags, the source item (or a new item generated from it) is inserted into the target list.

Comparison Callback Function

Each time the function wants to know the relative order of a target item and a source item, it calls the comparison function. If DPAM_SORTED was not given among the dwFlags, the comparison function will also be called repeatedly to determine the relative order of items in the same list.

The comparison function returns zero to indicate that the item at p1 matches the item at p2. A negative or positive result from the comparison function means respectively that the item at p1 is ordered before or after the item at p2.

Merge Callback Function

Each time the function modifies the target list, it calls the merge function. The type of modification is described by the uMsg argument:

DPAMM_MERGE (1) found matching items;
choose what to insert in target
DPAMM_DELETE (2) removed unmatched item from target;
notification only, no response
DPAMM_INSERT (3) found unmatched item in source;
choose what to insert in target

For the DPAMM_MERGE modification, p1 points to an item in the target list and p2 to a matching item in the source list. The callback returns the address of an item that is to take the place of the given target item. It may actually be the given target item, but obvious alternatives are the given source item or a copy or a new item generated from the two given items. If the callback returns NULL, merging is aborted and DPA_Merge fails (with the target list in what is perhaps best regarded as an undefined state).

DPAMM_DELETE notifies that the item at p1 has been removed from the target list. This case arises because the given target item had no match in the source list and DPAM_INTERSECT was specified among the dwFlags. The p2 argument is NULL. The return value is ignored.

For the DPAMM_INSERT modification, the source item at p1 has no match in the target list and DPAM_UNION was specified among the dwFlags. The callback returns the address of an item that is to be inserted into the target list. It may actually be the given source item, but an obvious alternative is an item generated from it (e.g., a copy). The p2 argument is NULL. If the callback returns NULL, merging is aborted and DPA_Merge fails (with the target list in what is perhaps best regarded as an undefined state).

Interpretation and Coding Error

That DPAM_UNION without DPAM_INTERSECT forms the target list as a generalised union of the two input lists is plain enough. The target ends with one item for every item that was in either list but not both, and one item for every matching pair.

Interpretation of other combinations of these bits in dwFlags is far from obvious just from the function as actually implemented. Note in particular that if the combination of DPAM_INTERSECT without DPAM_UNION is meant to produce a generalised intersection of the two input lists, then step 1 is a coding error.

Availability

The DPA_Merge function is exported from COMCTL32.DLL as ordinal 11 in version 4.71 and higher.

Though this function dates from as long ago as 1997, it was still not documented by Microsoft in the MSDN Library at least as late as the CD edition dated January 2004.

This function has, however, got documented since then (in 2006, or perhaps some time during 2005), albeit as requiring “version 5.0 or later”. This article now uses Microsoft’s nomenclature.